├── .drone.yml ├── .gitignore ├── LICENSE ├── README.md ├── command.go ├── const.go ├── const_strings.go ├── example └── example.go ├── go.mod ├── model.go ├── processor.go ├── reflection ├── reflection.go └── reflection_test.go ├── request ├── async.go ├── request.go └── sync.go ├── util └── util.go └── znp.go /.drone.yml: -------------------------------------------------------------------------------- 1 | pipeline: 2 | test: 3 | image: golang 4 | commands: 5 | - go install 6 | - go test ./... -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | go.sum 2 | payload.test 3 | profile_cpu.out 4 | profile.svg 5 | old.txt 6 | new.txt 7 | strings/ 8 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yevhen Zadyra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZigBee Network Processor (ZNP) Interface 2 | 3 | [![Build Status](https://cloud.drone.io/api/badges/dyrkin/znp-go/status.svg??branch=master)](https://cloud.drone.io/dyrkin/znp-go) 4 | 5 | ## Overview 6 | 7 | ZNP is used for communication between the host and a ZigBee device through a serial port. You can issue Monitor and Test (MT) commands to the 8 | ZigBee target from your application. 9 | 10 | I tested it with cc253**1**, but it might work with cc253**X** 11 | 12 | ## Example 13 | 14 | To use it you need to provide a reference to an unp instance: 15 | 16 | ```go 17 | import ( 18 | "go.bug.st/serial.v1" 19 | "github.com/davecgh/go-spew/spew" 20 | "github.com/dyrkin/unp-go" 21 | "github.com/dyrkin/znp-go" 22 | ) 23 | 24 | func main() { 25 | mode := &serial.Mode{ 26 | BaudRate: 115200, 27 | } 28 | 29 | port, err := serial.Open("/dev/tty.usbmodem14101", mode) 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | port.SetRTS(true) 34 | 35 | u := unp.New(1, port) 36 | z := znp.New(u) 37 | z.Start() 38 | } 39 | ``` 40 | 41 | Then you be able to run commands: 42 | 43 | ```go 44 | res, err := z.SysSetExtAddr("0x00124b00019c2ee9") 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | 49 | res, err = z.SapiZbPermitJoiningRequest("0xFF00", 200) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | ``` 54 | 55 | To receive async commands and errors, use `AsyncInbound()` and `Errors()` channels: 56 | 57 | ```go 58 | go func() { 59 | for { 60 | select { 61 | case err := <-z.Errors(): 62 | fmt.Printf("Error received: %s\n", err) 63 | case async := <-z.AsyncInbound(): 64 | fmt.Printf("Async received: %s\n", spew.Sdump(async)) 65 | } 66 | } 67 | }() 68 | ``` 69 | 70 | To log all ingoing and outgoing unp frames, use `InFramesLog()` and `OutFramesLog()` channels: 71 | 72 | ```go 73 | go func() { 74 | for { 75 | select { 76 | case frame := <-z.OutFramesLog(): 77 | fmt.Printf("Frame sent: %s\n", spew.Sdump(frame)) 78 | case frame := <-z.InFramesLog(): 79 | fmt.Printf("Frame received: %s\n", spew.Sdump(frame)) 80 | } 81 | } 82 | }() 83 | ``` 84 | 85 | See more [examples](example/example.go) 86 | 87 | -------------------------------------------------------------------------------- /command.go: -------------------------------------------------------------------------------- 1 | package znp 2 | 3 | import unp "github.com/dyrkin/unp-go" 4 | 5 | // =======AF======= 6 | 7 | func (znp *Znp) AfRegister(endPoint uint8, appProfID uint16, appDeviceID uint16, addDevVer uint8, 8 | latencyReq Latency, appInClusterList []uint16, appOutClusterList []uint16) (rsp *StatusResponse, err error) { 9 | req := &AfRegister{EndPoint: endPoint, AppProfID: appProfID, AppDeviceID: appDeviceID, 10 | AddDevVer: addDevVer, LatencyReq: latencyReq, AppInClusterList: appInClusterList, AppOutClusterList: appOutClusterList} 11 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x00, req, &rsp) 12 | return 13 | } 14 | 15 | func (znp *Znp) AfDataRequest(dstAddr string, dstEndpoint uint8, srcEndpoint uint8, clusterId uint16, 16 | transId uint8, options *AfDataRequestOptions, radius uint8, data []uint8) (rsp *StatusResponse, err error) { 17 | req := &AfDataRequest{DstAddr: dstAddr, DstEndpoint: dstEndpoint, SrcEndpoint: srcEndpoint, 18 | ClusterID: clusterId, TransID: transId, Options: options, Radius: radius, Data: data} 19 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x01, req, &rsp) 20 | return 21 | } 22 | 23 | func (znp *Znp) AfDataRequestExt(dstAddrMode AddrMode, dstAddr string, dstEndpoint uint8, dstPanId uint16, 24 | srcEndpoint uint8, clusterId uint16, transId uint8, options *AfDataRequestOptions, radius uint8, 25 | data []uint8) (rsp *StatusResponse, err error) { 26 | req := &AfDataRequestExt{DstAddrMode: dstAddrMode, DstAddr: dstAddr, DstEndpoint: dstEndpoint, DstPanID: dstPanId, SrcEndpoint: srcEndpoint, 27 | ClusterID: clusterId, TransID: transId, Options: options, Radius: radius, Data: data} 28 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x02, req, &rsp) 29 | return 30 | } 31 | 32 | func (znp *Znp) AfDataRequestSrcRtg(dstAddr string, dstEndpoint uint8, srcEndpoint uint8, clusterId uint16, 33 | transId uint8, options *AfDataRequestSrcRtgOptions, radius uint8, relayList []string, data []uint8) (rsp *StatusResponse, err error) { 34 | req := &AfDataRequestSrcRtg{DstAddr: dstAddr, DstEndpoint: dstEndpoint, SrcEndpoint: srcEndpoint, 35 | ClusterID: clusterId, TransID: transId, Options: options, Radius: radius, RelayList: relayList, Data: data} 36 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x03, req, &rsp) 37 | return 38 | } 39 | 40 | func (znp *Znp) AfInterPanCtl(command InterPanCommand, data AfInterPanCtlData) (rsp *StatusResponse, err error) { 41 | req := &AfInterPanCtl{Command: command, Data: data} 42 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x10, req, &rsp) 43 | return 44 | } 45 | 46 | func (znp *Znp) AfDataStore(index uint16, data []uint8) (rsp *StatusResponse, err error) { 47 | req := &AfDataStore{Index: index, Data: data} 48 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x11, req, &rsp) 49 | return 50 | } 51 | 52 | func (znp *Znp) AfDataRetrieve(timestamp uint32, index uint16, length uint8) (rsp *AfDataRetrieveResponse, err error) { 53 | req := &AfDataRetrieve{Timestamp: timestamp, Index: index, Length: length} 54 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x12, req, &rsp) 55 | return 56 | } 57 | 58 | func (znp *Znp) AfApsfConfigSet(endpoint uint8, frameDelay uint8, windowSize uint8) (rsp *StatusResponse, err error) { 59 | req := &AfApsfConfigSet{Endpoint: endpoint, FrameDelay: frameDelay, WindowSize: windowSize} 60 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_AF, 0x13, req, &rsp) 61 | return 62 | } 63 | 64 | // =======APP======= 65 | 66 | func (znp *Znp) AppMsg(appEndpoint uint8, dstAddr string, dstEndpoint uint8, clusterID uint16, 67 | message []uint8) (rsp *StatusResponse, err error) { 68 | req := &AppMsg{AppEndpoint: appEndpoint, DstAddr: dstAddr, DstEndpoint: dstEndpoint, 69 | ClusterID: clusterID, Message: message} 70 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP, 0x00, req, &rsp) 71 | return 72 | } 73 | 74 | func (znp *Znp) AppUserTest(srcEndpoint uint8, commandId uint16, parameter1 uint16, parameter2 uint16) (rsp *StatusResponse, err error) { 75 | req := &AppUserTest{SrcEndpoint: srcEndpoint, CommandID: commandId, Parameter1: parameter1, Parameter2: parameter2} 76 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP, 0x01, req, &rsp) 77 | return 78 | } 79 | 80 | // =======DEBUG======= 81 | 82 | func (znp *Znp) DebugSetThreshold(componentId uint8, threshold uint8) (rsp *StatusResponse, err error) { 83 | req := &DebugSetThreshold{ComponentID: componentId, Threshold: threshold} 84 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_DBG, 0x00, req, &rsp) 85 | return 86 | } 87 | 88 | func (znp *Znp) DebugMsg(str string) error { 89 | req := &DebugMsg{String: str} 90 | return znp.ProcessRequest(unp.C_AREQ, unp.S_DBG, 0x00, req, nil) 91 | } 92 | 93 | // =======MAC======= is not supported on my device 94 | 95 | // =======SAPI======= 96 | 97 | func (znp *Znp) SapiZbSystemReset() error { 98 | return znp.ProcessRequest(unp.C_AREQ, unp.S_SAPI, 0x09, nil, nil) 99 | } 100 | 101 | func (znp *Znp) SapiZbStartRequest() (rsp *EmptyResponse, err error) { 102 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x00, nil, &rsp) 103 | return 104 | } 105 | 106 | func (znp *Znp) SapiZbPermitJoiningRequest(destination string, timeout uint8) (rsp *StatusResponse, err error) { 107 | req := &SapiZbPermitJoiningRequest{Destination: destination, Timeout: timeout} 108 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x08, req, &rsp) 109 | return 110 | } 111 | 112 | func (znp *Znp) SapiZbBindDevice(create uint8, commandId uint16, destination string) (rsp *EmptyResponse, err error) { 113 | req := &SapiZbBindDevice{Create: create, CommandID: commandId, Destination: destination} 114 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x01, req, &rsp) 115 | return 116 | } 117 | 118 | func (znp *Znp) SapiZbAllowBind(timeout uint8) (rsp *EmptyResponse, err error) { 119 | req := &SapiZbAllowBind{Timeout: timeout} 120 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x02, req, &rsp) 121 | return 122 | } 123 | 124 | func (znp *Znp) SapiZbSendDataRequest(destination string, commandID uint16, handle uint8, 125 | ack uint8, radius uint8, data []uint8) (rsp *EmptyResponse, err error) { 126 | req := &SapiZbSendDataRequest{Destination: destination, CommandID: commandID, 127 | Handle: handle, Ack: ack, Radius: radius, Data: data} 128 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x03, req, &rsp) 129 | return 130 | } 131 | 132 | func (znp *Znp) SapiZbReadConfiguration(configID uint8) (rsp *SapiZbReadConfigurationResponse, err error) { 133 | req := &SapiZbReadConfiguration{ConfigID: configID} 134 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x04, req, &rsp) 135 | return 136 | } 137 | 138 | func (znp *Znp) SapiZbWriteConfiguration(configID uint8, value []uint8) (rsp *StatusResponse, err error) { 139 | req := &SapiZbWriteConfiguration{ConfigID: configID, Value: value} 140 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x05, req, &rsp) 141 | return 142 | } 143 | 144 | func (znp *Znp) SapiZbGetDeviceInfo(param uint8) (rsp *SapiZbGetDeviceInfoResponse, err error) { 145 | req := &SapiZbGetDeviceInfo{Param: param} 146 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x06, req, &rsp) 147 | return 148 | } 149 | 150 | func (znp *Znp) SapiZbFindDeviceRequest(searchKey string) (rsp *EmptyResponse, err error) { 151 | req := &SapiZbFindDeviceRequest{SearchKey: searchKey} 152 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SAPI, 0x07, req, &rsp) 153 | return 154 | } 155 | 156 | // =======SYS======= 157 | 158 | //SysReset is sent by the tester to reset the target device 159 | func (znp *Znp) SysResetReq(resetType byte) error { 160 | req := &SysResetReq{resetType} 161 | return znp.ProcessRequest(unp.C_AREQ, unp.S_SYS, 0x00, req, nil) 162 | } 163 | 164 | //SysPing issues PING requests to verify if a device is active and check the capability of the device. 165 | func (znp *Znp) SysPing() (rsp *SysPingResponse, err error) { 166 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x01, nil, &rsp) 167 | return 168 | } 169 | 170 | func (znp *Znp) SysVersion() (rsp *SysVersionResponse, err error) { 171 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x02, nil, &rsp) 172 | return 173 | } 174 | 175 | //SysSetExtAddr is used to set the extended address of the device 176 | func (znp *Znp) SysSetExtAddr(extAddr string) (rsp *StatusResponse, err error) { 177 | req := &SysSetExtAddr{ExtAddress: extAddr} 178 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x03, req, &rsp) 179 | return 180 | } 181 | 182 | //SysGetExtAddr is used to get the extended address of the device 183 | func (znp *Znp) SysGetExtAddr() (rsp *SysGetExtAddrResponse, err error) { 184 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x04, nil, &rsp) 185 | return 186 | } 187 | 188 | //SysRamRead is used by the tester to read a single memory location in the target RAM. The 189 | //command accepts an address value and returns the memory value present in the target RAM at that address. 190 | func (znp *Znp) SysRamRead(address uint16, len uint8) (rsp *SysRamReadResponse, err error) { 191 | req := &SysRamRead{Address: address, Len: len} 192 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x05, req, &rsp) 193 | return 194 | } 195 | 196 | //SysRamWrite is used by the tester to write to a particular location in the target RAM. The 197 | //command accepts an address location and a memory value. The memory value is written to the 198 | //address location in the target RAM. 199 | func (znp *Znp) SysRamWrite(address uint16, value []uint8) (rsp *StatusResponse, err error) { 200 | req := &SysRamWrite{Address: address, Value: value} 201 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x06, req, &rsp) 202 | return 203 | } 204 | 205 | //SysOsalNvRead is used by the tester to read a single memory item from the target non-volatile 206 | //memory. The command accepts an attribute Id value and data offset and returns the memory value 207 | //present in the target for the specified attribute Id. 208 | func (znp *Znp) SysOsalNvRead(id uint16, offset uint8) (rsp *StatusResponse, err error) { 209 | req := &SysOsalNvRead{ID: id, Offset: offset} 210 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x08, req, &rsp) 211 | return 212 | } 213 | 214 | //SysOsalNvWrite is used by the tester to write to a particular item in non-volatile memory. The 215 | //command accepts an attribute Id, data offset, data length, and attribute value. The attribute value is 216 | //written to the location specified for the attribute Id in the target. 217 | func (znp *Znp) SysOsalNvWrite(id uint16, offset uint8, value []uint8) (rsp *StatusResponse, err error) { 218 | req := &SysOsalNvWrite{ID: id, Offset: offset, Value: value} 219 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x09, req, &rsp) 220 | return 221 | } 222 | 223 | //SysOsalNvItemInit is used by the tester to create and initialize an item in non-volatile memory. The 224 | //NV item will be created if it does not already exist. The data for the new NV item will be left 225 | //uninitialized if the InitLen parameter is zero. When InitLen is non-zero, the data for the NV item 226 | //will be initialized (starting at offset of zero) with the values from InitData. Note that it is not 227 | //necessary to initialize the entire NV item (InitLen < ItemLen). It is also possible to create an NV 228 | //item that is larger than the maximum length InitData – use the SYS_OSAL_NV_WRITE 229 | //command to finish the initialization. 230 | func (znp *Znp) SysOsalNvItemInit(id uint16, itemLen uint16, initData []uint8) (rsp *StatusResponse, err error) { 231 | req := &SysOsalNvItemInit{ID: id, ItemLen: itemLen, InitData: initData} 232 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x07, req, &rsp) 233 | return 234 | } 235 | 236 | //SysOsalNvDelete is used by the tester to delete an item from the non-volatile memory. The ItemLen 237 | //parameter must match the length of the NV item or the command will fail. Use this command with 238 | //caution – deleted items cannot be recovered. 239 | func (znp *Znp) SysOsalNvDelete(id uint16, itemLen uint16) (rsp *StatusResponse, err error) { 240 | req := &SysOsalNvDelete{ID: id, ItemLen: itemLen} 241 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x12, req, &rsp) 242 | return 243 | } 244 | 245 | //SysOsalNvLength is used by the tester to get the length of an item in non-volatile memory. A 246 | //returned length of zero indicates that the NV item does not exist. 247 | func (znp *Znp) SysOsalNvLength(id uint16) (rsp *SysOsalNvLengthResponse, err error) { 248 | req := &SysOsalNvLength{ID: id} 249 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x13, req, &rsp) 250 | return 251 | } 252 | 253 | //SysOsalStartTimer is used by the tester to start a timer event. The event will expired after the indicated 254 | //amount of time and a notification will be sent back to the tester. 255 | func (znp *Znp) SysOsalStartTimer(id uint8, timeout uint16) (rsp *StatusResponse, err error) { 256 | req := &SysOsalStartTimer{ID: id, Timeout: timeout} 257 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x0A, req, &rsp) 258 | return 259 | } 260 | 261 | //SysOsalStopTimer is used by the tester to stop a timer event. 262 | func (znp *Znp) SysOsalStopTimer(id uint8) (rsp *StatusResponse, err error) { 263 | req := &SysOsalStopTimer{ID: id} 264 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x0B, req, &rsp) 265 | return 266 | } 267 | 268 | //SysRandom is used by the tester to get a random 16-bit number. 269 | func (znp *Znp) SysRandom() (rsp *SysRandomResponse, err error) { 270 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x0C, nil, &rsp) 271 | return 272 | } 273 | 274 | //SysAdcRead reads a value from the ADC based on specified channel and resolution. 275 | func (znp *Znp) SysAdcRead(channel Channel, resolution Resolution) (rsp *SysAdcReadResponse, err error) { 276 | req := &SysAdcRead{Channel: channel, Resolution: resolution} 277 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x0D, req, &rsp) 278 | return 279 | } 280 | 281 | //SysGpio is used by the tester to control the 4 GPIO pins on the CC2530-ZNP build. 282 | func (znp *Znp) SysGpio(operation Operation, value uint8) (rsp *SysGpioResponse, err error) { 283 | req := &SysGpio{Operation: operation, Value: value} 284 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x0E, req, &rsp) 285 | return 286 | } 287 | 288 | //SysSetTime is used by the tester to set the target system date and time. The time can be 289 | //specified in “seconds since 00:00:00 on January 1, 2000” or in parsed date/time components 290 | func (znp *Znp) SysSetTime(utcTime uint32, hour uint8, minute uint8, second uint8, 291 | month uint8, day uint8, year uint16) (rsp *StatusResponse, err error) { 292 | req := &SysTime{UTCTime: utcTime, Hour: hour, Minute: minute, Second: second, Month: month, Day: day, Year: year} 293 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x10, req, &rsp) 294 | return 295 | } 296 | 297 | //SysGetTime is used by the tester to get the target system date and time. The time is returned in 298 | //seconds since 00:00:00 on January 1, 2000” and parsed date/time components. 299 | func (znp *Znp) SysGetTime() (rsp *SysTime, err error) { 300 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x11, nil, &rsp) 301 | return 302 | } 303 | 304 | //SysSetTxPower is used by the tester to set the target system radio transmit power. The returned TX 305 | //power is the actual setting applied to the radio – nearest characterized value for the specific radio 306 | func (znp *Znp) SysSetTxPower(txPower uint8) (rsp *SysSetTxPowerResponse, err error) { 307 | req := &SysSetTxPower{TXPower: txPower} 308 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x14, req, &rsp) 309 | return 310 | } 311 | 312 | //SysZDiagsInitStats is used to initialize the statistics table in NV memory. 313 | func (znp *Znp) SysZDiagsInitStats() (rsp *StatusResponse, err error) { 314 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x17, nil, &rsp) 315 | return 316 | } 317 | 318 | //SysZDiagsClearStats is used to clear the statistics table. To clear data in NV (including the Boot 319 | //Counter) the clearNV flag shall be set to TRUE. 320 | func (znp *Znp) SysZDiagsClearStats(clearNV uint8) (rsp *SysZDiagsClearStatsResponse, err error) { 321 | req := &SysZDiagsClearStats{ClearNV: clearNV} 322 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x18, req, &rsp) 323 | return 324 | } 325 | 326 | //SysZDiagsGetStats is used to read a specific system (attribute) ID statistics and/or metrics value. 327 | func (znp *Znp) SysZDiagsGetStats(attributeID uint16) (rsp *SysZDiagsGetStatsResponse, err error) { 328 | req := &SysZDiagsGetStats{AttributeID: attributeID} 329 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x19, req, &rsp) 330 | return 331 | } 332 | 333 | //SysZDiagsRestoreStatsNv is used to restore the statistics table from NV into the RAM table. 334 | func (znp *Znp) SysZDiagsRestoreStatsNv() (rsp *StatusResponse, err error) { 335 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x1A, nil, &rsp) 336 | return 337 | } 338 | 339 | //SysZDiagsSaveStatsToNv is used to save the statistics table from RAM to NV. 340 | func (znp *Znp) SysZDiagsSaveStatsToNv() (rsp *SysZDiagsSaveStatsToNvResponse, err error) { 341 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x1B, nil, &rsp) 342 | return 343 | } 344 | 345 | //SysNvCreate is used to attempt to create an item in non-volatile memory. 346 | func (znp *Znp) SysNvCreate(sysID uint8, itemID uint16, subID uint16, length uint32) (rsp *StatusResponse, err error) { 347 | req := &SysNvCreate{SysID: sysID, ItemID: itemID, SubID: subID, Length: length} 348 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x30, req, &rsp) 349 | return 350 | } 351 | 352 | //SysNvDelete is used to attempt to delete an item in non-volatile memory. 353 | func (znp *Znp) SysNvDelete(sysID uint8, itemID uint16, subID uint16) (rsp *StatusResponse, err error) { 354 | req := &SysNvDelete{SysID: sysID, ItemID: itemID, SubID: subID} 355 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x31, req, &rsp) 356 | return 357 | } 358 | 359 | //SysNvLength is used to get the length of an item in non-volatile memory. 360 | func (znp *Znp) SysNvLength(sysID uint8, itemID uint16, subID uint16) (rsp *SysNvLengthResponse, err error) { 361 | req := &SysNvLength{SysID: sysID, ItemID: itemID, SubID: subID} 362 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x32, req, &rsp) 363 | return 364 | } 365 | 366 | //SysNvRead is used to read an item in non-volatile memory 367 | func (znp *Znp) SysNvRead(sysID uint8, itemID uint16, subID uint16, offset uint16, length uint8) (rsp *SysNvReadResponse, err error) { 368 | req := &SysNvRead{SysID: sysID, ItemID: itemID, SubID: subID, Offset: offset, Length: length} 369 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x33, req, &rsp) 370 | return 371 | } 372 | 373 | //SysNvWrite is used to write an item in non-volatile memory 374 | func (znp *Znp) SysNvWrite(sysID uint8, itemID uint16, subID uint16, offset uint16, value []uint8) (rsp *StatusResponse, err error) { 375 | req := &SysNvWrite{SysID: sysID, ItemID: itemID, SubID: subID, Offset: offset, Value: value} 376 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x34, req, &rsp) 377 | return 378 | } 379 | 380 | //SysNvUpdate is used to update an item in non-volatile memory 381 | func (znp *Znp) SysNvUpdate(sysID uint8, itemID uint16, subID uint16, value []uint8) (rsp *StatusResponse, err error) { 382 | req := &SysNvUpdate{SysID: sysID, ItemID: itemID, SubID: subID, Value: value} 383 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x35, req, &rsp) 384 | return 385 | } 386 | 387 | //SysNvCompact is used to compact the active page in non-volatile memory 388 | func (znp *Znp) SysNvCompact(threshold uint16) (rsp *StatusResponse, err error) { 389 | req := &SysNvCompact{Threshold: threshold} 390 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x36, req, &rsp) 391 | return 392 | } 393 | 394 | //SysNvReadExt is used by the tester to read a single memory item from the target non-volatile 395 | //memory. The command accepts an attribute Id value and data offset and returns the memory value 396 | //present in the target for the specified attribute Id. 397 | func (znp *Znp) SysNvReadExt(id uint16, offset uint16) (rsp *SysNvReadResponse, err error) { 398 | req := &SysNvReadExt{ID: id, Offset: offset} 399 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x08, req, &rsp) 400 | return 401 | } 402 | 403 | //SysNvWrite is used to write an item in non-volatile memory 404 | func (znp *Znp) SysNvWriteExt(id uint16, offset uint16, value []uint8) (rsp *StatusResponse, err error) { 405 | req := &SysNvWriteExt{ID: id, Offset: offset, Value: value} 406 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_SYS, 0x09, req, &rsp) 407 | return 408 | } 409 | 410 | // =======UTIL======= 411 | 412 | //UtilGetDeviceInfo is sent by the tester to retrieve the device info. 413 | func (znp *Znp) UtilGetDeviceInfo() (rsp *UtilGetDeviceInfoResponse, err error) { 414 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x00, nil, &rsp) 415 | return 416 | } 417 | 418 | //UtilGetNvInfo is used by the tester to read a block of parameters from non-volatile storage of the 419 | //target device. 420 | func (znp *Znp) UtilGetNvInfo() (rsp *UtilGetNvInfoResponse, err error) { 421 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x01, nil, &rsp) 422 | return 423 | } 424 | 425 | //UtilSetPanId stores a PanId value into non-volatile memory to be used the next time the target device resets. 426 | func (znp *Znp) UtilSetPanId(panId uint16) (rsp *StatusResponse, err error) { 427 | req := &UtilSetPanId{PanID: panId} 428 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x02, req, &rsp) 429 | return 430 | } 431 | 432 | //UtilSetChannels is used to store a channel select bit-mask into non-volatile memory to be used the 433 | //next time the target device resets. 434 | func (znp *Znp) UtilSetChannels(channels *Channels) (rsp *StatusResponse, err error) { 435 | req := &UtilSetChannels{Channels: channels} 436 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x03, req, &rsp) 437 | return 438 | } 439 | 440 | //UtilSetSecLevel is used to store a security level value into non-volatile memory to be used the next time the target device 441 | //resets. 442 | func (znp *Znp) UtilSetSecLevel(secLevel uint8) (rsp *StatusResponse, err error) { 443 | req := &UtilSetSecLevel{SecLevel: secLevel} 444 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x04, req, &rsp) 445 | return 446 | } 447 | 448 | //UtilSetPreCfgKey is used to store a pre-configured key array into non-volatile memory to be used the 449 | //next time the target device resets. 450 | func (znp *Znp) UtilSetPreCfgKey(preCfgKey [16]uint8) (rsp *StatusResponse, err error) { 451 | req := &UtilSetPreCfgKey{PreCfgKey: preCfgKey} 452 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x05, req, &rsp) 453 | return 454 | } 455 | 456 | //UtilCallbackSubCmd subscribes/unsubscribes to layer callbacks. For particular subsystem callbacks to 457 | //work, the software must be compiled with a special flag that is unique to that subsystem to enable 458 | //the callback mechanism. For example to enable ZDO callbacks, MT_ZDO_CB_FUNC flag must 459 | //be compiled when the software is built. For complete list of callback compile flags, check section 460 | //1.2 or “Z-Stack Compile Options” document. 461 | func (znp *Znp) UtilCallbackSubCmd(subsystemID SubsystemId, action Action) (rsp *StatusResponse, err error) { 462 | req := &UtilCallbackSubCmd{SubsystemID: subsystemID, Action: action} 463 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x06, req, &rsp) 464 | return 465 | } 466 | 467 | //UtilKeyEvent sends key and shift codes to the application that registered for key events. The keys parameter is a 468 | //bit mask, allowing for multiple keys in a single command. The return status indicates success if 469 | //the command is processed by a registered key handler, not whether the key code was used. Not all 470 | //applications support all key or shift codes but there is no indication when a key code is dropped. 471 | func (znp *Znp) UtilKeyEvent(keys *Keys, shift Shift) (rsp *StatusResponse, err error) { 472 | req := &UtilKeyEvent{Keys: keys, Shift: shift} 473 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x07, req, &rsp) 474 | return 475 | } 476 | 477 | //UtilTimeAlive is used by the tester to get the board’s time alive 478 | func (znp *Znp) UtilTimeAlive() (rsp *UtilTimeAliveResponse, err error) { 479 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x09, nil, &rsp) 480 | return 481 | } 482 | 483 | //UtilLedControl is used by the tester to control the LEDs on the board. 484 | func (znp *Znp) UtilLedControl(ledID uint8, mode Mode) (rsp *StatusResponse, err error) { 485 | req := &UtilLedControl{LedID: ledID, Mode: mode} 486 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x0A, req, &rsp) 487 | return 488 | } 489 | 490 | //UtilLoopback is used by the tester to test data buffer loopback. 491 | func (znp *Znp) UtilLoopback(data []uint8) (rsp *UtilLoopback, err error) { 492 | req := &UtilLoopback{Data: data} 493 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x10, req, &rsp) 494 | return 495 | } 496 | 497 | //UtilDataReq is used by the tester to effect a MAC MLME Poll Request 498 | func (znp *Znp) UtilDataReq(securityUse uint8) (rsp *StatusResponse, err error) { 499 | req := &UtilDataReq{SecurityUse: securityUse} 500 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x11, req, &rsp) 501 | return 502 | } 503 | 504 | //UtilSrcMatchEnable is used to enable AUTOPEND and source address matching. 505 | func (znp *Znp) UtilSrcMatchEnable() (rsp *StatusResponse, err error) { 506 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x20, nil, &rsp) 507 | return 508 | } 509 | 510 | //UtilSrcMatchAddEntry is used to add a short or extended address to the source address table 511 | func (znp *Znp) UtilSrcMatchAddEntry(addrMode AddrMode, address string, panId uint16) (rsp *StatusResponse, err error) { 512 | req := &UtilSrcMatchAddEntry{AddrMode: addrMode, Address: address, PanID: panId} 513 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x21, req, &rsp) 514 | return 515 | } 516 | 517 | //UtilSrcMatchDelEntry is used to delete a short or extended address from the source address table. 518 | func (znp *Znp) UtilSrcMatchDelEntry(addrMode AddrMode, address string, panId uint16) (rsp *StatusResponse, err error) { 519 | req := &UtilSrcMatchDelEntry{AddrMode: addrMode, Address: address, PanID: panId} 520 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x22, req, &rsp) 521 | return 522 | } 523 | 524 | //UtilSrcMatchCheckSrcAddr is used to delete a short or extended address from the source address table. 525 | func (znp *Znp) UtilSrcMatchCheckSrcAddr(addrMode AddrMode, address string, panId uint16) (rsp *StatusResponse, err error) { 526 | req := &UtilSrcMatchCheckSrcAddr{AddrMode: addrMode, Address: address, PanID: panId} 527 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x23, req, &rsp) 528 | return 529 | } 530 | 531 | //UtilSrcMatchAckAllPending is used to enable/disable acknowledging all packets with pending bit set. 532 | func (znp *Znp) UtilSrcMatchAckAllPending(option Action) (rsp *StatusResponse, err error) { 533 | req := &UtilSrcMatchAckAllPending{Option: option} 534 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x24, req, &rsp) 535 | return 536 | } 537 | 538 | //UtilSrcMatchCheckAllPending is used to check if acknowledging all packets with pending bit set is enabled. 539 | func (znp *Znp) UtilSrcMatchCheckAllPending() (rsp *UtilSrcMatchCheckAllPendingResponse, err error) { 540 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x25, nil, &rsp) 541 | return 542 | } 543 | 544 | //UtilAddrMgrExtAddrLookup is a proxy call to the AddrMgrEntryLookupExt() function. 545 | func (znp *Znp) UtilAddrMgrExtAddrLookup(extAddr string) (rsp *UtilAddrMgrExtAddrLookupResponse, err error) { 546 | req := &UtilAddrMgrExtAddrLookup{ExtAddr: extAddr} 547 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x40, req, &rsp) 548 | return 549 | } 550 | 551 | //UtilAddrMgrAddrLookup is a proxy call to the AddrMgrEntryLookupNwk() function. 552 | func (znp *Znp) UtilAddrMgrAddrLookup(nwkAddr string) (rsp *UtilAddrMgrAddrLookupResponse, err error) { 553 | req := &UtilAddrMgrAddrLookup{NwkAddr: nwkAddr} 554 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x41, req, &rsp) 555 | return 556 | } 557 | 558 | //UtilApsmeLinkKeyDataGet retrieves APS link key data, Tx and Rx frame counters 559 | func (znp *Znp) UtilApsmeLinkKeyDataGet(extAddr string) (rsp *UtilApsmeLinkKeyDataGetResponse, err error) { 560 | req := &UtilApsmeLinkKeyDataGet{ExtAddr: extAddr} 561 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x44, req, &rsp) 562 | return 563 | } 564 | 565 | //UtilApsmeLinkKeyNvIdGet is a proxy call to the APSME_LinkKeyNvIdGet() function. 566 | func (znp *Znp) UtilApsmeLinkKeyNvIdGet(extAddr string) (rsp *UtilApsmeLinkKeyNvIdGetResponse, err error) { 567 | req := &UtilApsmeLinkKeyNvIdGet{ExtAddr: extAddr} 568 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x45, req, &rsp) 569 | return 570 | } 571 | 572 | //UtilApsmeRequestKeyCmd is used to send a request key to the Trust Center from an originator device who 573 | //wants to exchange messages with a partner device. 574 | func (znp *Znp) UtilApsmeRequestKeyCmd(partnerAddr string) (rsp *StatusResponse, err error) { 575 | req := &UtilApsmeRequestKeyCmd{PartnerAddr: partnerAddr} 576 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x4B, req, &rsp) 577 | return 578 | } 579 | 580 | //UtilAssocCount is a proxy call to the AssocCount() function 581 | func (znp *Znp) UtilAssocCount(startRelation Relation, endRelation Relation) (rsp *UtilAssocCountResponse, err error) { 582 | req := &UtilAssocCount{StartRelation: startRelation, EndRelation: endRelation} 583 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x48, req, &rsp) 584 | return 585 | } 586 | 587 | //UtilAssocFindDevice is a proxy call to the AssocFindDevice() function. 588 | func (znp *Znp) UtilAssocFindDevice(number uint8) (rsp *UtilAssocFindDeviceResponse, err error) { 589 | req := &UtilAssocFindDevice{Number: number} 590 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x49, req, &rsp) 591 | return 592 | } 593 | 594 | //UtilAssocGetWithAddr is a proxy call to the AssocGetWithAddress() function. 595 | func (znp *Znp) UtilAssocGetWithAddr(extAddr string, nwkAddr string) (rsp *UtilAssocGetWithAddrResponse, err error) { 596 | req := &UtilAssocGetWithAddr{ExtAddr: extAddr, NwkAddr: nwkAddr} 597 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x4A, req, &rsp) 598 | return 599 | } 600 | 601 | //UtilBindAddEntry is a proxy call to the bindAddEntry() function 602 | func (znp *Znp) UtilBindAddEntry(addrMode AddrMode, dstAddr string, dstEndpoint uint8, clusterIds []uint16) (rsp *UtilBindAddEntryResponse, err error) { 603 | req := &UtilBindAddEntry{AddrMode: addrMode, DstAddr: dstAddr, DstEndpoint: dstEndpoint, ClusterIDs: clusterIds} 604 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x4D, req, &rsp) 605 | return 606 | } 607 | 608 | //UtilZclKeyEstInitEst is a proxy call to zclGeneral_KeyEstablish_InitiateKeyEstablishment(). 609 | func (znp *Znp) UtilZclKeyEstInitEst(taskId uint8, seqNum uint8, endPoint uint8, addrMode AddrMode, addr string) (rsp *StatusResponse, err error) { 610 | req := &UtilZclKeyEstInitEst{TaskID: taskId, SeqNum: seqNum, EndPoint: endPoint, AddrMode: addrMode, Addr: addr} 611 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x80, req, &rsp) 612 | return 613 | } 614 | 615 | //UtilZclKeyEstSign is a proxy call to zclGeneral_KeyEstablishment_ECDSASign(). 616 | func (znp *Znp) UtilZclKeyEstSign(input []uint8) (rsp *UtilZclKeyEstSignResponse, err error) { 617 | req := &UtilZclKeyEstSign{Input: input} 618 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x81, req, &rsp) 619 | return 620 | } 621 | 622 | //UtilSrngGen is used to generate Secure Random Number. It generates 1,000,000 bits in sets of 623 | //100 bytes. As in 100 bytes of secure random numbers are generated until 1,000,000 bits are 624 | //generated. 100 bytes are generate 625 | func (znp *Znp) UtilSrngGen() (rsp *UtilSrngGenResponse, err error) { 626 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_UTIL, 0x4C, nil, &rsp) 627 | return 628 | } 629 | 630 | //UtilSyncReq is an asynchronous request/response handshake. 631 | func (znp *Znp) UtilSyncReq() (err error) { 632 | err = znp.ProcessRequest(unp.C_AREQ, unp.S_UTIL, 0xE0, nil, nil) 633 | return 634 | } 635 | 636 | // =======ZDO======= 637 | 638 | //ZdoNwkAddrReq will request the device to send a “Network Address Request”. This message sends a 639 | //broadcast message looking for a 16 bit address with a known 64 bit IEEE address. You must 640 | //subscribe to “ZDO Network Address Response” to receive the response to this message. Check 641 | //section 3.0.1.7 for more details on callback subscription. The response message listed below only 642 | //indicates whether or not the message was received properly. 643 | func (znp *Znp) ZdoNwkAddrReq(ieeeAddress string, reqType ReqType, startIndex uint8) (rsp *StatusResponse, err error) { 644 | req := &ZdoNwkAddrReq{IEEEAddress: ieeeAddress, ReqType: reqType, StartIndex: startIndex} 645 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x00, req, &rsp) 646 | return 647 | } 648 | 649 | //ZdoIeeeAddrReq will request a device’s IEEE 64-bit address. You must subscribe to “ZDO IEEE 650 | //Address Response” to receive the data response to this message. The response message listed 651 | //below only indicates whether or not the message was received properly. 652 | func (znp *Znp) ZdoIeeeAddrReq(shortAddr string, reqType ReqType, startIndex uint8) (rsp *StatusResponse, err error) { 653 | req := &ZdoIeeeAddrReq{ShortAddr: shortAddr, ReqType: reqType, StartIndex: startIndex} 654 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x01, req, &rsp) 655 | return 656 | } 657 | 658 | //ZdoNodeDescReq is generated to inquire about the Node Descriptor information of the destination 659 | //device. 660 | func (znp *Znp) ZdoNodeDescReq(dstAddr string, nwkAddrOfInterest string) (rsp *StatusResponse, err error) { 661 | req := &ZdoNodeDescReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest} 662 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x02, req, &rsp) 663 | return 664 | } 665 | 666 | //ZdoPowerDescReq is generated to inquire about the Power Descriptor information of the destination 667 | //device. 668 | func (znp *Znp) ZdoPowerDescReq(dstAddr string, nwkAddrOfInterest string) (rsp *StatusResponse, err error) { 669 | req := &ZdoPowerDescReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest} 670 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x03, req, &rsp) 671 | return 672 | } 673 | 674 | //ZdoSimpleDescReq is generated to inquire as to the Simple Descriptor of the destination device’s 675 | //Endpoint. 676 | func (znp *Znp) ZdoSimpleDescReq(dstAddr string, nwkAddrOfInterest string, endpoint uint8) (rsp *StatusResponse, err error) { 677 | req := &ZdoSimpleDescReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest, Endpoint: endpoint} 678 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x04, req, &rsp) 679 | return 680 | } 681 | 682 | //ZdoActiveEpReq is generated to request a list of active endpoint from the destination device 683 | func (znp *Znp) ZdoActiveEpReq(dstAddr string, nwkAddrOfInterest string) (rsp *StatusResponse, err error) { 684 | req := &ZdoActiveEpReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest} 685 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x05, req, &rsp) 686 | return 687 | } 688 | 689 | //ZdoMatchDescReq is generated to request the device match descriptor 690 | func (znp *Znp) ZdoMatchDescReq(dstAddr string, nwkAddrOfInterest string, profileId uint16, 691 | inClusterList []uint16, outClusterList []uint16) (rsp *StatusResponse, err error) { 692 | req := &ZdoMatchDescReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest, ProfileID: profileId, 693 | InClusterList: inClusterList, OutClusterList: outClusterList} 694 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x06, req, &rsp) 695 | return 696 | } 697 | 698 | //ZdoComplexDescReq is generated to request for the destination device’s complex descriptor. 699 | func (znp *Znp) ZdoComplexDescReq(dstAddr string, nwkAddrOfInterest string) (rsp *StatusResponse, err error) { 700 | req := &ZdoComplexDescReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest} 701 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x07, req, &rsp) 702 | return 703 | } 704 | 705 | //ZdoUserDescReq is generated to request for the destination device’s user descriptor 706 | func (znp *Znp) ZdoUserDescReq(dstAddr string, nwkAddrOfInterest string) (rsp *StatusResponse, err error) { 707 | req := &ZdoUserDescReq{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest} 708 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x08, req, &rsp) 709 | return 710 | } 711 | 712 | //ZdoEndDeviceAnnce will cause the device to issue an “End device announce” broadcast packet to the 713 | //network. This is typically used by an end-device to announce itself to the network. 714 | func (znp *Znp) ZdoEndDeviceAnnce(nwkAddr string, ieeeAddr string, capabilities *CapInfo) (rsp *StatusResponse, err error) { 715 | req := &ZdoEndDeviceAnnce{NwkAddr: nwkAddr, IEEEAddr: ieeeAddr, Capabilities: capabilities} 716 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x0A, req, &rsp) 717 | return 718 | } 719 | 720 | //ZdoUserDescSet is generated to write a User Descriptor value to the targeted device. 721 | func (znp *Znp) ZdoUserDescSet(dstAddr string, nwkAddrOfInterest string, userDescriptor string) (rsp *StatusResponse, err error) { 722 | req := &ZdoUserDescSet{DstAddr: dstAddr, NWKAddrOfInterest: nwkAddrOfInterest, UserDescriptor: userDescriptor} 723 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x0B, req, &rsp) 724 | return 725 | } 726 | 727 | //ZdoServerDiscReq is used for local device to discover the location of a particular system server or 728 | //servers as indicated by the ServerMask parameter. The destination addressing on this request is 729 | //‘broadcast to all RxOnWhenIdle devices’. 730 | func (znp *Znp) ZdoServerDiscReq(serverMask *ServerMask) (rsp *StatusResponse, err error) { 731 | req := &ZdoServerDiscReq{ServerMask: serverMask} 732 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x0C, req, &rsp) 733 | return 734 | } 735 | 736 | //ZdoEndDeviceBindReq is generated to request an End Device Bind with the destination device. 737 | func (znp *Znp) ZdoEndDeviceBindReq(dstAddr string, localCoordinatorAddr string, ieeeAddr string, endpoint uint8, 738 | profileId uint16, inClusterList []uint16, outClusterList []uint16) (rsp *StatusResponse, err error) { 739 | req := &ZdoEndDeviceBindReq{DstAddr: dstAddr, LocalCoordinatorAddr: localCoordinatorAddr, IEEEAddr: ieeeAddr, 740 | Endpoint: endpoint, ProfileID: profileId, InClusterList: inClusterList, OutClusterList: outClusterList} 741 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x20, req, &rsp) 742 | return 743 | } 744 | 745 | //ZdoBindReq is generated to request an End Device Bind with the destination device. 746 | func (znp *Znp) ZdoBindReq(dstAddr string, srcAddress string, srcEndpoint uint8, clusterId uint16, 747 | dstAddrMode AddrMode, dstAddress string, dstEndpoint uint8) (rsp *StatusResponse, err error) { 748 | req := &ZdoBindUnbindReq{DstAddr: dstAddr, SrcAddress: srcAddress, SrcEndpoint: srcEndpoint, ClusterID: clusterId, 749 | DstAddrMode: dstAddrMode, DstAddress: dstAddress, DstEndpoint: dstEndpoint} 750 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x21, req, &rsp) 751 | return 752 | } 753 | 754 | //ZdoUnbindReq is generated to request a un-bind. 755 | func (znp *Znp) ZdoUnbindReq(dstAddr string, srcAddress string, srcEndpoint uint8, clusterId uint16, 756 | dstAddrMode AddrMode, dstAddress string, dstEndpoint uint8) (rsp *StatusResponse, err error) { 757 | req := &ZdoBindUnbindReq{DstAddr: dstAddr, SrcAddress: srcAddress, SrcEndpoint: srcEndpoint, ClusterID: clusterId, 758 | DstAddrMode: dstAddrMode, DstAddress: dstAddress, DstEndpoint: dstEndpoint} 759 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x22, req, &rsp) 760 | return 761 | } 762 | 763 | //ZdoMgmtNwkDiskReq is generated to request the destination device to perform a network discovery 764 | func (znp *Znp) ZdoMgmtNwkDiskReq(dstAddr string, scanChannels *Channels, scanDuration uint8, startIndex uint8) (rsp *StatusResponse, err error) { 765 | req := &ZdoMgmtNwkDiskReq{DstAddr: dstAddr, ScanChannels: scanChannels, ScanDuration: scanDuration, StartIndex: startIndex} 766 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x30, req, &rsp) 767 | return 768 | } 769 | 770 | //ZdoMgmtLqiReq is generated to request the destination device to perform a LQI query of other 771 | //devices in the network. 772 | func (znp *Znp) ZdoMgmtLqiReq(dstAddr string, startIndex uint8) (rsp *StatusResponse, err error) { 773 | req := &ZdoMgmtLqiReq{DstAddr: dstAddr, StartIndex: startIndex} 774 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x31, req, &rsp) 775 | return 776 | } 777 | 778 | //ZdoMgmtRtgReq is generated to request the Routing Table of the destination device 779 | func (znp *Znp) ZdoMgmtRtgReq(dstAddr string, startIndex uint8) (rsp *StatusResponse, err error) { 780 | req := &ZdoMgmtRtgReq{DstAddr: dstAddr, StartIndex: startIndex} 781 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x32, req, &rsp) 782 | return 783 | } 784 | 785 | //ZdoMgmtBindReq is generated to request the Binding Table of the destination device. 786 | func (znp *Znp) ZdoMgmtBindReq(dstAddr string, startIndex uint8) (rsp *StatusResponse, err error) { 787 | req := &ZdoMgmtBindReq{DstAddr: dstAddr, StartIndex: startIndex} 788 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x33, req, &rsp) 789 | return 790 | } 791 | 792 | //ZdoMgmtLeaveReq is generated to request a Management Leave Request for the target device 793 | func (znp *Znp) ZdoMgmtLeaveReq(dstAddr string, deviceAddr string, removeChildrenRejoin *RemoveChildrenRejoin) (rsp *StatusResponse, err error) { 794 | req := &ZdoMgmtLeaveReq{DstAddr: dstAddr, DeviceAddr: deviceAddr, RemoveChildrenRejoin: removeChildrenRejoin} 795 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x34, req, &rsp) 796 | return 797 | } 798 | 799 | //ZdoMgmtDirectJoinReq is generated to request the Management Direct Join Request of a designated 800 | //device. 801 | func (znp *Znp) ZdoMgmtDirectJoinReq(dstAddr string, deviceAddr string, capInfo *CapInfo) (rsp *StatusResponse, err error) { 802 | req := &ZdoMgmtDirectJoinReq{DstAddr: dstAddr, DeviceAddr: deviceAddr, CapInfo: capInfo} 803 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x35, req, &rsp) 804 | return 805 | } 806 | 807 | //ZdoMgmtPermitJoinReq is generated to set the Permit Join for the destination device. 808 | func (znp *Znp) ZdoMgmtPermitJoinReq(addrMode AddrMode, dstAddr string, duration uint8, tcSignificance uint8) (rsp *StatusResponse, err error) { 809 | req := &ZdoMgmtPermitJoinReq{AddrMode: addrMode, DstAddr: dstAddr, Duration: duration, TCSignificance: tcSignificance} 810 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x36, req, &rsp) 811 | return 812 | } 813 | 814 | //ZdoMgmtNwkUpdateReq is provided to allow updating of network configuration parameters or to request 815 | //information from devices on network conditions in the local operating environment. 816 | func (znp *Znp) ZdoMgmtNwkUpdateReq(dstAddr string, dstAddrMode AddrMode, channelMask *Channels, scanDuration uint8) (rsp *StatusResponse, err error) { 817 | req := &ZdoMgmtNwkUpdateReq{DstAddr: dstAddr, DstAddrMode: dstAddrMode, ChannelMask: channelMask, ScanDuration: scanDuration} 818 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x37, req, &rsp) 819 | return 820 | } 821 | 822 | //ZdoMsgCbRegister registers for a ZDO callback (see reference [3], “6. ZDO Message Requests” for 823 | //example usage). 824 | func (znp *Znp) ZdoMsgCbRegister(clusterId uint16) (rsp *StatusResponse, err error) { 825 | req := &ZdoMsgCbRegister{ClusterID: clusterId} 826 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x3E, req, &rsp) 827 | return 828 | } 829 | 830 | //ZdoMsgCbRemove removes a registration for a ZDO callback (see reference [3], “6. ZDO Message 831 | //Requests” for example usage). 832 | func (znp *Znp) ZdoMsgCbRemove(clusterId uint16) (rsp *StatusResponse, err error) { 833 | req := &ZdoMsgCbRemove{ClusterID: clusterId} 834 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x3F, req, &rsp) 835 | return 836 | } 837 | 838 | //ZdoStartupFromApp starts the device in the network. 839 | func (znp *Znp) ZdoStartupFromApp(startDelay uint16) (rsp *ZdoStartupFromAppResponse, err error) { 840 | req := &ZdoStartupFromApp{StartDelay: startDelay} 841 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x40, req, &rsp) 842 | return 843 | } 844 | 845 | //ZdoSetLinkKey starts the device in the network. 846 | func (znp *Znp) ZdoSetLinkKey(shortAddr string, ieeeAddr string, linkKeyData [16]uint8) (rsp *StatusResponse, err error) { 847 | req := &ZdoSetLinkKey{ShortAddr: shortAddr, IEEEAddr: ieeeAddr, LinkKeyData: linkKeyData} 848 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x23, req, &rsp) 849 | return 850 | } 851 | 852 | //ZdoRemoveLinkKey removes the application link key of a given device. 853 | func (znp *Znp) ZdoRemoveLinkKey(ieeeAddr string) (rsp *StatusResponse, err error) { 854 | req := &ZdoRemoveLinkKey{IEEEAddr: ieeeAddr} 855 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x24, req, &rsp) 856 | return 857 | } 858 | 859 | //ZdoGetLinkKey retrieves the application link key of a given device. 860 | func (znp *Znp) ZdoGetLinkKey(ieeeAddr string) (rsp *ZdoGetLinkKeyResponse, err error) { 861 | req := &ZdoGetLinkKey{IEEEAddr: ieeeAddr} 862 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x25, req, &rsp) 863 | return 864 | } 865 | 866 | //ZdoNwkDiscoveryReq is used to initiate a network discovery (active scan). 867 | //Strange response SecOldFrmCount(0xa1) 868 | func (znp *Znp) ZdoNwkDiscoveryReq(scanChannels *Channels, scanDuration uint8) (rsp *StatusResponse, err error) { 869 | req := &ZdoNwkDiscoveryReq{ScanChannels: scanChannels, ScanDuration: scanDuration} 870 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x26, req, &rsp) 871 | return 872 | } 873 | 874 | //ZdoJoinReq is used to request the device to join itself to a parent device on a network. 875 | func (znp *Znp) ZdoJoinReq(logicalChannel uint8, panId uint16, extendedPanId uint64, 876 | chosenParent string, parentDepth uint8, stackProfile uint8) (rsp *StatusResponse, err error) { 877 | req := &ZdoJoinReq{LogicalChannel: logicalChannel, PanID: panId, ExtendedPanID: extendedPanId, 878 | ChosenParent: chosenParent, ParentDepth: parentDepth, StackProfile: stackProfile} 879 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x27, req, &rsp) 880 | return 881 | } 882 | 883 | //ZdoSetRejoinParameters is used to set rejoin backoff duration and rejoin scan duration for an end device 884 | func (znp *Znp) ZdoSetRejoinParameters(backoffDuration uint32, scanDuration uint32) (rsp *StatusResponse, err error) { 885 | req := &ZdoSetRejoinParameters{BackoffDuration: backoffDuration, ScanDuration: scanDuration} 886 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0xCC, req, &rsp) 887 | return 888 | } 889 | 890 | //ZdoSecAddLinkKey handles the ZDO security add link key extension message. 891 | func (znp *Znp) ZdoSecAddLinkKey(shortAddress string, extendedAddress string, key [16]uint8) (rsp *StatusResponse, err error) { 892 | req := &ZdoSecAddLinkKey{ShortAddress: shortAddress, ExtendedAddress: extendedAddress, Key: key} 893 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x42, req, &rsp) 894 | return 895 | } 896 | 897 | //ZdoSecEntryLookupExt handles the ZDO security entry lookup extended extension message 898 | func (znp *Znp) ZdoSecEntryLookupExt(extendedAddress string, entry [5]uint8) (rsp *ZdoSecEntryLookupExtResponse, err error) { 899 | req := &ZdoSecEntryLookupExt{ExtendedAddress: extendedAddress, Entry: entry} 900 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x43, req, &rsp) 901 | return 902 | } 903 | 904 | //ZdoSecDeviceRemove handles the ZDO security remove device extended extension message. 905 | func (znp *Znp) ZdoSecDeviceRemove(extendedAddress string) (rsp *StatusResponse, err error) { 906 | req := &ZdoSecDeviceRemove{ExtendedAddress: extendedAddress} 907 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x44, req, &rsp) 908 | return 909 | } 910 | 911 | //ZdoExtRouteDisc handles the ZDO route discovery extension message. 912 | func (znp *Znp) ZdoExtRouteDisc(destinationAddress string, options uint8, radius uint8) (rsp *StatusResponse, err error) { 913 | req := &ZdoExtRouteDisc{DestinationAddress: destinationAddress, Options: options, Radius: radius} 914 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x45, req, &rsp) 915 | return 916 | } 917 | 918 | //ZdoExtRouteCheck handles the ZDO route check extension message. 919 | func (znp *Znp) ZdoExtRouteCheck(destinationAddress string, rtStatus uint8, options uint8) (rsp *StatusResponse, err error) { 920 | req := &ZdoExtRouteCheck{DestinationAddress: destinationAddress, RTStatus: rtStatus, Options: options} 921 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x46, req, &rsp) 922 | return 923 | } 924 | 925 | //ZdoExtRemoveGroup handles the ZDO extended remove group extension message. 926 | func (znp *Znp) ZdoExtRemoveGroup(endpoint uint8, groupId uint16) (rsp *StatusResponse, err error) { 927 | req := &ZdoExtRemoveGroup{Endpoint: endpoint, GroupID: groupId} 928 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x47, req, &rsp) 929 | return 930 | } 931 | 932 | //ZdoExtRemoveAllGroup handles the ZDO extended remove all group extension message. 933 | func (znp *Znp) ZdoExtRemoveAllGroup(endpoint uint8) (rsp *StatusResponse, err error) { 934 | req := &ZdoExtRemoveAllGroup{Endpoint: endpoint} 935 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x48, req, &rsp) 936 | return 937 | } 938 | 939 | //ZdoExtFindAllGroupsEndpoint handles the ZDO extension find all groups for endpoint message 940 | func (znp *Znp) ZdoExtFindAllGroupsEndpoint(endpoint uint8, groupList []uint16) (rsp *ZdoExtFindAllGroupsEndpointResponse, err error) { 941 | req := &ZdoExtFindAllGroupsEndpoint{Endpoint: endpoint, GroupList: groupList} 942 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x49, req, &rsp) 943 | return 944 | } 945 | 946 | //ZdoExtFindGroup handles the ZDO extension find all groups for endpoint message 947 | func (znp *Znp) ZdoExtFindGroup(endpoint uint8, groupID uint16) (rsp *ZdoExtFindGroupResponse, err error) { 948 | req := &ZdoExtFindGroup{Endpoint: endpoint, GroupID: groupID} 949 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x4A, req, &rsp) 950 | return 951 | } 952 | 953 | //ZdoExtAddGroup handles the ZDO extension add group message. 954 | func (znp *Znp) ZdoExtAddGroup(endpoint uint8, groupID uint16, groupName string) (rsp *StatusResponse, err error) { 955 | req := &ZdoExtAddGroup{Endpoint: endpoint, GroupID: groupID, GroupName: groupName} 956 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x4B, req, &rsp) 957 | return 958 | } 959 | 960 | //ZdoExtCountAllGroups handles the ZDO extension count all groups message. 961 | func (znp *Znp) ZdoExtCountAllGroups() (rsp *ZdoExtCountAllGroupsResponse, err error) { 962 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x4C, nil, &rsp) 963 | return 964 | } 965 | 966 | //ZdoExtRxIdle handles the ZDO extension Get/Set RxOnIdle to ZMac message 967 | func (znp *Znp) ZdoExtRxIdle(setFlag uint8, setValue uint8) (rsp *StatusResponse, err error) { //very unclear from the docs and the code 968 | req := &ZdoExtRxIdle{SetFlag: setFlag, SetValue: setValue} 969 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x4D, req, &rsp) 970 | return 971 | } 972 | 973 | //ZdoExtUpdateNwkKey handles the ZDO security update network key extension message. 974 | func (znp *Znp) ZdoExtUpdateNwkKey(destinationAddress string, keySeqNum uint8, key [128]uint8) (rsp *StatusResponse, err error) { 975 | req := &ZdoExtUpdateNwkKey{DestinationAddress: destinationAddress, KeySeqNum: keySeqNum, Key: key} 976 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x4E, req, &rsp) 977 | return 978 | } 979 | 980 | //ZdoExtSwitchNwkKey handles the ZDO security switch network key extension message. 981 | func (znp *Znp) ZdoExtSwitchNwkKey(destinationAddress string, keySeqNum uint8) (rsp *StatusResponse, err error) { 982 | req := &ZdoExtSwitchNwkKey{DestinationAddress: destinationAddress, KeySeqNum: keySeqNum} 983 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x4F, req, &rsp) 984 | return 985 | } 986 | 987 | //ZdoExtNwkInfo handles the ZDO extension network message. 988 | func (znp *Znp) ZdoExtNwkInfo() (rsp *ZdoExtNwkInfoResponse, err error) { 989 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x50, nil, &rsp) 990 | return 991 | } 992 | 993 | //ZdoExtSeqApsRemoveReq handles the ZDO extension Security Manager APS Remove Request message. 994 | func (znp *Znp) ZdoExtSeqApsRemoveReq(nwkAddress string, extendedAddress string, parentAddress string) (rsp *StatusResponse, err error) { 995 | req := &ZdoExtSeqApsRemoveReq{NwkAddress: nwkAddress, ExtendedAddress: extendedAddress, ParentAddress: parentAddress} 996 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x51, req, &rsp) 997 | return 998 | } 999 | 1000 | //ZdoForceConcentratorChange forces a network concentrator change by resetting zgConcentratorEnable and 1001 | //zgConcentratorDiscoveryTime from NV and set nwk event. 1002 | func (znp *Znp) ZdoForceConcentratorChange() error { 1003 | return znp.ProcessRequest(unp.C_AREQ, unp.S_ZDO, 0x52, nil, nil) 1004 | } 1005 | 1006 | //ZdoExtSeqApsRemoveReq set parameters not settable through NV. 1007 | func (znp *Znp) ZdoExtSetParams(useMulticast uint8) (rsp *StatusResponse, err error) { 1008 | req := &ZdoExtSetParams{UseMulticast: useMulticast} 1009 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x53, req, &rsp) 1010 | return 1011 | } 1012 | 1013 | //ZdoNwkAddrOfInterestReq handles ZDO network address of interest request. 1014 | func (znp *Znp) ZdoNwkAddrOfInterestReq(destAddr string, nwkAddrOfInterest string, cmd uint8) (rsp *StatusResponse, err error) { 1015 | req := &ZdoNwkAddrOfInterestReq{DestAddr: destAddr, NwkAddrOfInterest: nwkAddrOfInterest, Cmd: cmd} 1016 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_ZDO, 0x29, req, &rsp) 1017 | return 1018 | } 1019 | 1020 | // =======APP_CNF======= 1021 | 1022 | //AppCnfSetNwkFrameCounter sets the network frame counter to the value specified in the Frame Counter Value. 1023 | //For projects with multiple instances of frame counter, the message sets the frame counter of the 1024 | //current network. 1025 | func (znp *Znp) AppCnfSetNwkFrameCounter(frameCounterValue uint8) (rsp *StatusResponse, err error) { 1026 | req := &AppCnfSetNwkFrameCounter{FrameCounterValue: frameCounterValue} 1027 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0xFF, req, &rsp) 1028 | return 1029 | } 1030 | 1031 | //AppCnfSetDefaultEndDeviceTimeout sets the default value used by parent device to expire legacy child devices. 1032 | func (znp *Znp) AppCnfSetDefaultEndDeviceTimeout(timeout Timeout) (rsp *StatusResponse, err error) { 1033 | req := &AppCnfSetDefaultEndDeviceTimeout{Timeout: timeout} 1034 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x01, req, &rsp) 1035 | return 1036 | } 1037 | 1038 | //AppCnfSetEndDeviceTimeout sets in ZED the timeout value to be send to parent device for child expiring. 1039 | func (znp *Znp) AppCnfSetEndDeviceTimeout(timeout Timeout) (rsp *StatusResponse, err error) { 1040 | req := &AppCnfSetEndDeviceTimeout{Timeout: timeout} 1041 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x02, req, &rsp) 1042 | return 1043 | } 1044 | 1045 | //AppCnfSetAllowRejoinTcPolicy sets the AllowRejoin TC policy. 1046 | func (znp *Znp) AppCnfSetAllowRejoinTcPolicy(allowRejoin uint8) (rsp *StatusResponse, err error) { 1047 | req := &AppCnfSetAllowRejoinTcPolicy{AllowRejoin: allowRejoin} 1048 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x03, req, &rsp) 1049 | return 1050 | } 1051 | 1052 | //AppCnfBdbStartCommissioning set the commissioning methods to be executed. Initialization of BDB is executed with this call, 1053 | //regardless of its parameters. 1054 | func (znp *Znp) AppCnfBdbStartCommissioning(commissioningMode CommissioningMode) (rsp *StatusResponse, err error) { 1055 | req := &AppCnfBdbStartCommissioning{CommissioningMode: commissioningMode} 1056 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x05, req, &rsp) 1057 | return 1058 | } 1059 | 1060 | //AppCnfBdbSetChannel sets BDB primary or secondary channel masks. 1061 | func (znp *Znp) AppCnfBdbSetChannel(isPrimary uint8, channel *Channels) (rsp *StatusResponse, err error) { 1062 | req := &AppCnfBdbSetChannel{IsPrimary: isPrimary, Channel: channel} 1063 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x08, req, &rsp) 1064 | return 1065 | } 1066 | 1067 | //AppCnfBdbAddInstallCode add a preconfigured key (plain key or IC) to Trust Center device. 1068 | func (znp *Znp) AppCnfBdbAddInstallCode(installCodeFormat InstallCodeFormat, ieeeAddr string, installCode []uint8) (rsp *StatusResponse, err error) { 1069 | req := &AppCnfBdbAddInstallCode{InstallCodeFormat: installCodeFormat, IEEEAddr: ieeeAddr, InstallCode: installCode} 1070 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x04, req, &rsp) 1071 | return 1072 | } 1073 | 1074 | //AppCnfBdbSetTcRequireKeyExchange sets the policy flag on Trust Center device to mandate or not the TCLK exchange procedure. 1075 | func (znp *Znp) AppCnfBdbSetTcRequireKeyExchange(bdbTrustCenterRequireKeyExchange uint8) (rsp *StatusResponse, err error) { 1076 | req := &AppCnfBdbSetTcRequireKeyExchange{BdbTrustCenterRequireKeyExchange: bdbTrustCenterRequireKeyExchange} 1077 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x09, req, &rsp) 1078 | return 1079 | } 1080 | 1081 | //AppCnfBdbSetJoinUsesInstallCodeKey sets the policy to mandate or not the usage of an Install Code upon joining. 1082 | func (znp *Znp) AppCnfBdbSetJoinUsesInstallCodeKey(bdbJoinUsesInstallCodeKey uint8) (rsp *StatusResponse, err error) { 1083 | req := &AppCnfBdbSetJoinUsesInstallCodeKey{BdbJoinUsesInstallCodeKey: bdbJoinUsesInstallCodeKey} 1084 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x06, req, &rsp) 1085 | return 1086 | } 1087 | 1088 | //AppCnfBdbSetActiveDefaultCentralizedKey on joining devices, set the default key or an install code to attempt to join the network. 1089 | func (znp *Znp) AppCnfBdbSetActiveDefaultCentralizedKey(useGlobal uint8, installCode [18]uint8) (rsp *StatusResponse, err error) { 1090 | req := &AppCnfBdbSetActiveDefaultCentralizedKey{UseGlobal: useGlobal, InstallCode: installCode} 1091 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x07, req, &rsp) 1092 | return 1093 | } 1094 | 1095 | //AppCnfBdbZedAttemptRecoverNwk instruct the ZED to try to rejoin its previews network. Use only in ZED devices. 1096 | func (znp *Znp) AppCnfBdbZedAttemptRecoverNwk(useGlobal uint8, installCode [18]uint8) (rsp *StatusResponse, err error) { 1097 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_APP_CNF, 0x0A, nil, &rsp) 1098 | return 1099 | } 1100 | 1101 | // =======GP======= 1102 | 1103 | //GpDataReq callback to receive notifications from BDB process. 1104 | func (znp *Znp) GpDataReq(action GpAction, txOptions *TxOptions, applicationId uint8, srcId uint32, 1105 | gpdIEEEAddress string, endpoint uint8, gpdCommandId uint8, gpdasdu []uint8, 1106 | gpepHandle uint8, gpTxQueueEntryLifetime uint32) (rsp *StatusResponse, err error) { 1107 | req := &GpDataReq{Action: action, TxOptions: txOptions, ApplicationID: applicationId, 1108 | SrcID: srcId, GPDIEEEAddress: gpdIEEEAddress, Endpoint: endpoint, 1109 | GPDCommandID: gpdCommandId, GPDASDU: gpdasdu, GPEPHandle: gpepHandle, 1110 | GPTxQueueEntryLifetime: gpTxQueueEntryLifetime} 1111 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_GP, 0x01, req, &rsp) 1112 | return 1113 | } 1114 | 1115 | //GpSecRsp provides a mechanism for the Green Power EndPoint to provide security data into 1116 | //the dGP stub. 1117 | func (znp *Znp) GpSecRsp(status GpStatus, dGPStubHandle uint8, applicationID uint8, srcID uint32, 1118 | gpdIEEEAddress string, endpoint uint8, gpdFSecurityLevel uint8, gpdFKeyType uint8, 1119 | gpdKey [16]uint8, gpdSecurityFrameCounter uint32) (rsp *StatusResponse, err error) { 1120 | req := &GpSecRsp{Status: status, DGPStubHandle: dGPStubHandle, ApplicationID: applicationID, 1121 | SrcID: srcID, GPDIEEEAddress: gpdIEEEAddress, Endpoint: endpoint, GPDFSecurityLevel: gpdFSecurityLevel, 1122 | GPDFKeyType: gpdFKeyType, GPDKey: gpdKey, GPDSecurityFrameCounter: gpdSecurityFrameCounter} 1123 | err = znp.ProcessRequest(unp.C_SREQ, unp.S_GP, 0x02, req, &rsp) 1124 | return 1125 | } 1126 | 1127 | type key struct { 1128 | subsystem unp.Subsystem 1129 | command byte 1130 | } 1131 | 1132 | var asyncCommandRegistry = make(map[key]interface{}) 1133 | 1134 | func init() { 1135 | //AF 1136 | asyncCommandRegistry[key{unp.S_AF, 0x80}] = &AfDataConfirm{} 1137 | asyncCommandRegistry[key{unp.S_AF, 0x83}] = &AfReflectError{} 1138 | asyncCommandRegistry[key{unp.S_AF, 0x81}] = &AfIncomingMessage{} 1139 | asyncCommandRegistry[key{unp.S_AF, 0x82}] = &AfIncomingMessageExt{} 1140 | 1141 | //DEBUG 1142 | asyncCommandRegistry[key{unp.S_DBG, 0x00}] = &DebugMsg{} 1143 | 1144 | //SAPI 1145 | asyncCommandRegistry[key{unp.S_SAPI, 0x80}] = &SapiZbStartConfirm{} 1146 | asyncCommandRegistry[key{unp.S_SAPI, 0x81}] = &SapiZbBindConfirm{} 1147 | asyncCommandRegistry[key{unp.S_SAPI, 0x82}] = &SapiZbAllowBindConfirm{} 1148 | asyncCommandRegistry[key{unp.S_SAPI, 0x83}] = &SapiZbSendDataConfirm{} 1149 | asyncCommandRegistry[key{unp.S_SAPI, 0x87}] = &SapiZbReceiveDataIndication{} 1150 | asyncCommandRegistry[key{unp.S_SAPI, 0x85}] = &SapiZbFindDeviceConfirm{} 1151 | 1152 | //SYS 1153 | asyncCommandRegistry[key{unp.S_SYS, 0x80}] = &SysResetInd{} 1154 | asyncCommandRegistry[key{unp.S_SYS, 0x81}] = &SysOsalTimerExpired{} 1155 | 1156 | //UTIL 1157 | asyncCommandRegistry[key{unp.S_UTIL, 0xE0}] = &UtilSyncReq{} 1158 | asyncCommandRegistry[key{unp.S_UTIL, 0xE1}] = &UtilZclKeyEstablishInd{} 1159 | 1160 | //ZDO 1161 | asyncCommandRegistry[key{unp.S_ZDO, 0x80}] = &ZdoNwkAddrRsp{} 1162 | asyncCommandRegistry[key{unp.S_ZDO, 0x81}] = &ZdoIEEEAddrRsp{} 1163 | asyncCommandRegistry[key{unp.S_ZDO, 0x82}] = &ZdoNodeDescRsp{} 1164 | asyncCommandRegistry[key{unp.S_ZDO, 0x83}] = &ZdoPowerDescRsp{} 1165 | asyncCommandRegistry[key{unp.S_ZDO, 0x84}] = &ZdoSimpleDescRsp{} 1166 | asyncCommandRegistry[key{unp.S_ZDO, 0x85}] = &ZdoActiveEpRsp{} 1167 | asyncCommandRegistry[key{unp.S_ZDO, 0x86}] = &ZdoMatchDescRsp{} 1168 | asyncCommandRegistry[key{unp.S_ZDO, 0x87}] = &ZdoComplexDescRsp{} 1169 | asyncCommandRegistry[key{unp.S_ZDO, 0x88}] = &ZdoUserDescRsp{} 1170 | asyncCommandRegistry[key{unp.S_ZDO, 0x89}] = &ZdoUserDescConf{} 1171 | asyncCommandRegistry[key{unp.S_ZDO, 0x8A}] = &ZdoServerDiscRsp{} 1172 | asyncCommandRegistry[key{unp.S_ZDO, 0xA0}] = &ZdoEndDeviceBindRsp{} 1173 | asyncCommandRegistry[key{unp.S_ZDO, 0xA1}] = &ZdoBindRsp{} 1174 | asyncCommandRegistry[key{unp.S_ZDO, 0xA2}] = &ZdoUnbindRsp{} 1175 | asyncCommandRegistry[key{unp.S_ZDO, 0xB0}] = &ZdoMgmtNwkDiscRsp{} 1176 | asyncCommandRegistry[key{unp.S_ZDO, 0xB1}] = &ZdoMgmtLqiRsp{} 1177 | asyncCommandRegistry[key{unp.S_ZDO, 0xB2}] = &ZdoMgmtRtgRsp{} 1178 | asyncCommandRegistry[key{unp.S_ZDO, 0xB3}] = &ZdoMgmtBindRsp{} 1179 | asyncCommandRegistry[key{unp.S_ZDO, 0xB4}] = &ZdoMgmtLeaveRsp{} 1180 | asyncCommandRegistry[key{unp.S_ZDO, 0xB5}] = &ZdoMgmtDirectJoinRsp{} 1181 | asyncCommandRegistry[key{unp.S_ZDO, 0xB6}] = &ZdoMgmtPermitJoinRsp{} 1182 | asyncCommandRegistry[key{unp.S_ZDO, 0xC0}] = &ZdoStateChangeInd{} 1183 | asyncCommandRegistry[key{unp.S_ZDO, 0xC1}] = &ZdoEndDeviceAnnceInd{} 1184 | asyncCommandRegistry[key{unp.S_ZDO, 0xC2}] = &ZdoMatchDescRpsSent{} 1185 | asyncCommandRegistry[key{unp.S_ZDO, 0xC3}] = &ZdoStatusErrorRsp{} 1186 | asyncCommandRegistry[key{unp.S_ZDO, 0xC4}] = &ZdoSrcRtgInd{} 1187 | asyncCommandRegistry[key{unp.S_ZDO, 0xC5}] = &ZdoBeaconNotifyInd{} 1188 | asyncCommandRegistry[key{unp.S_ZDO, 0xC6}] = &ZdoJoinCnf{} 1189 | asyncCommandRegistry[key{unp.S_ZDO, 0xC7}] = &ZdoNwkDiscoveryCnf{} 1190 | asyncCommandRegistry[key{unp.S_ZDO, 0xC9}] = &ZdoLeaveInd{} 1191 | asyncCommandRegistry[key{unp.S_ZDO, 0xFF}] = &ZdoMsgCbIncoming{} 1192 | asyncCommandRegistry[key{unp.S_ZDO, 0xCA}] = &ZdoTcDevInd{} 1193 | asyncCommandRegistry[key{unp.S_ZDO, 0xCB}] = &ZdoPermitJoinInd{} 1194 | 1195 | //APP 1196 | asyncCommandRegistry[key{unp.S_APP_CNF, 0x80}] = &AppCnfBdbCommissioningNotification{} 1197 | 1198 | //GP 1199 | asyncCommandRegistry[key{unp.S_GP, 0x01}] = &GpDataReq{} 1200 | asyncCommandRegistry[key{unp.S_GP, 0x02}] = &GpSecRsp{} 1201 | asyncCommandRegistry[key{unp.S_GP, 0x05}] = &GpDataCnf{} 1202 | asyncCommandRegistry[key{unp.S_GP, 0x03}] = &GpSecReq{} 1203 | asyncCommandRegistry[key{unp.S_GP, 0x04}] = &GpDataInd{} 1204 | } 1205 | -------------------------------------------------------------------------------- /const.go: -------------------------------------------------------------------------------- 1 | package znp 2 | 3 | type Latency uint8 4 | 5 | const ( 6 | LatencyNoLatency Latency = iota 7 | LatencyFastBeacons 8 | LatencySlowBeacons 9 | ) 10 | 11 | type StartupFromAppStatus uint8 12 | 13 | const ( 14 | StartupFromAppStatusRestoredNetworkState StartupFromAppStatus = 0x00 15 | StartupFromAppStatusNewNetworkState StartupFromAppStatus = 0x01 16 | StartupFromAppStatusLeaveAndNotStarted StartupFromAppStatus = 0x02 17 | ) 18 | 19 | type Status uint8 20 | 21 | const ( 22 | StatusSuccess Status = 0x00 23 | StatusFailure Status = 0x01 24 | StatusInvalidParameter Status = 0x02 25 | 26 | StatusItemCreatedAndInitialized Status = 0x09 27 | StatusInitializationFailed Status = 0x0a 28 | StatusBadLength Status = 0x0c 29 | 30 | // ZStack status values must start at 0x10, after the generic status values (defined in comdef.h) 31 | StatusMemError Status = 0x10 32 | StatusBufferFull Status = 0x11 33 | StatusUnsupportedMode Status = 0x12 34 | StatusMacMemError Status = 0x13 35 | 36 | StatusSapiInProgress Status = 0x20 37 | StatusSapiTimeout Status = 0x21 38 | StatusSapiInit Status = 0x22 39 | 40 | StatusNotAuthorized Status = 0x7E 41 | 42 | StatusMalformedCmd Status = 0x80 43 | StatusUnsupClusterCmd Status = 0x81 44 | 45 | StatusZdpInvalidEp Status = 0x82 // Invalid endpoint value 46 | StatusZdpNotActive Status = 0x83 // Endpoint not described by a simple desc. 47 | StatusZdpNotSupported Status = 0x84 // Optional feature not supported 48 | StatusZdpTimeout Status = 0x85 // Operation has timed out 49 | StatusZdpNoMatch Status = 0x86 // No match for end device bind 50 | StatusZdpNoEntry Status = 0x88 // Unbind request failed, no entry 51 | StatusZdpNoDescriptor Status = 0x89 // Child descriptor not available 52 | StatusZdpInsufficientSpace Status = 0x8a // Insufficient space to support operation 53 | StatusZdpNotPermitted Status = 0x8b // Not in proper state to support operation 54 | StatusZdpTableFull Status = 0x8c // No table space to support operation 55 | StatusZdpNotAuthorized Status = 0x8d // Permissions indicate request not authorized 56 | StatusZdpBindingTableFull Status = 0x8e // No binding table space to support operation 57 | 58 | // OTA Status values 59 | StatusOtaAbort Status = 0x95 60 | StatusOtaImageInvalid Status = 0x96 61 | StatusOtaWaitForData Status = 0x97 62 | StatusOtaNoImageAvailable Status = 0x98 63 | StatusOtaRequireMoreImage Status = 0x99 64 | 65 | // APS status values 66 | StatusApsFail Status = 0xb1 67 | StatusApsTableFull Status = 0xb2 68 | StatusApsIllegalRequest Status = 0xb3 69 | StatusApsInvalidBinding Status = 0xb4 70 | StatusApsUnsupportedAttrib Status = 0xb5 71 | StatusApsNotSupported Status = 0xb6 72 | StatusApsNoAck Status = 0xb7 73 | StatusApsDuplicateEntry Status = 0xb8 74 | StatusApsNoBoundDevice Status = 0xb9 75 | StatusApsNotAllowed Status = 0xba 76 | StatusApsNotAuthenticated Status = 0xbb 77 | 78 | // Security status values 79 | StatusSecNoKey Status = 0xa1 80 | StatusSecOldFrmCount Status = 0xa2 81 | StatusSecMaxFrmCount Status = 0xa3 82 | StatusSecCcmFail Status = 0xa4 83 | StatusSecFailure Status = 0xad 84 | 85 | // NWK status values 86 | StatusNwkInvalidParam Status = 0xc1 87 | StatusNwkInvalidRequest Status = 0xc2 88 | StatusNwkNotPermitted Status = 0xc3 89 | StatusNwkStartupFailure Status = 0xc4 90 | StatusNwkAlreadyPresent Status = 0xc5 91 | StatusNwkSyncFailure Status = 0xc6 92 | StatusNwkTableFull Status = 0xc7 93 | StatusNwkUnknownDevice Status = 0xc8 94 | StatusNwkUnsupportedAttribute Status = 0xc9 95 | StatusNwkNoNetworks Status = 0xca 96 | StatusNwkLeaveUnconfirmed Status = 0xcb 97 | StatusNwkNoAck Status = 0xcc // not in spec 98 | StatusNwkNoRoute Status = 0xcd 99 | 100 | // MAC status values 101 | // ZMacSuccess Status = 0x00 102 | StatusMacBeaconLoss Status = 0xe0 103 | StatusMacChannelAccessFailure Status = 0xe1 104 | StatusMacDenied Status = 0xe2 105 | StatusMacDisableTrxFailure Status = 0xe3 106 | StatusMacFailedSecurityCheck Status = 0xe4 107 | StatusMacFrameTooLong Status = 0xe5 108 | StatusMacInvalidGTS Status = 0xe6 109 | StatusMacInvalidHandle Status = 0xe7 110 | StatusMacInvalidParameter Status = 0xe8 111 | StatusMacNoACK Status = 0xe9 112 | StatusMacNoBeacon Status = 0xea 113 | StatusMacNoData Status = 0xeb 114 | StatusMacNoShortAddr Status = 0xec 115 | StatusMacOutOfCap Status = 0xed 116 | StatusMacPANIDConflict Status = 0xee 117 | StatusMacRealignment Status = 0xef 118 | StatusMacTransactionExpired Status = 0xf0 119 | StatusMacTransactionOverFlow Status = 0xf1 120 | StatusMacTxActive Status = 0xf2 121 | StatusMacUnAvailableKey Status = 0xf3 122 | StatusMacUnsupportedAttribute Status = 0xf4 123 | StatusMacUnsupported Status = 0xf5 124 | StatusMacSrcMatchInvalidIndex Status = 0xff 125 | ) 126 | 127 | type AddrMode uint8 128 | 129 | const ( 130 | AddrModeAddrNotPresent AddrMode = iota 131 | AddrModeAddrGroup 132 | AddrModeAddr16Bit 133 | AddrModeAddr64Bit 134 | AddrModeAddrBroadcast AddrMode = 15 //or 0xFF?????? 135 | ) 136 | 137 | type InterPanCommand uint8 138 | 139 | const ( 140 | InterPanCommandInterPanClr InterPanCommand = iota 141 | InterPanCommandInterPanSet 142 | InterPanCommandInterPanReg 143 | InterPanCommandInterPanChk 144 | ) 145 | 146 | type Channel uint8 147 | 148 | const ( 149 | ChannelAIN0 Channel = iota 150 | ChannelAIN1 151 | ChannelAIN2 152 | ChannelAIN3 153 | ChannelAIN4 154 | ChannelAIN5 155 | ChannelAIN6 156 | ChannelAIN7 157 | ChannelTemperatureSensor Channel = 0x0E + iota 158 | ChannelVoltageReading 159 | ) 160 | 161 | type Resolution uint8 162 | 163 | const ( 164 | Resolution8Bit Resolution = iota 165 | Resolution10Bit 166 | Resolution12Bit 167 | Resolution14Bit 168 | ) 169 | 170 | type Operation uint8 171 | 172 | const ( 173 | OperationSetDirection Operation = iota 174 | OperationSetInputMode 175 | OperationSet 176 | OperationClear 177 | OperationToggle 178 | OperationRead 179 | ) 180 | 181 | type Reason uint8 182 | 183 | const ( 184 | ReasonPowerUp Reason = iota 185 | ReasonExternal 186 | ReasonWatchDog 187 | ) 188 | 189 | type DeviceState uint8 190 | 191 | const ( 192 | DeviceStateInitializedNotStartedAutomatically DeviceState = iota 193 | DeviceStateInitializedNotConnectedToAnything 194 | DeviceStateDiscoveringPANsToJoin 195 | DeviceStateJoiningPAN 196 | DeviceStateRejoiningPAN 197 | DeviceStateJoinedButNotAuthenticated 198 | DeviceStateStartedAsDeviceAfterAuthentication 199 | DeviceStateDeviceJoinedAuthenticatedAndIsRouter 200 | DeviceStateStartingAsZigBeeCoordinator 201 | DeviceStateStartedAsZigBeeCoordinator 202 | DeviceStateDeviceHasLostInformationAboutItsParent 203 | DeviceStateDeviceSendingKeepAliveToParent 204 | DeviceStateDeviceWaitingBeforeRejoin 205 | DeviceStateReJoiningPANInSecureModeScanningAllChannels 206 | DeviceStateReJoiningPANInTrustCenterModeScanningCurrentChannel 207 | DeviceStateReJoiningPANInTrustCenterModeScanningAllChannels 208 | ) 209 | 210 | type SubsystemId uint16 211 | 212 | const ( 213 | SubsystemIdSys SubsystemId = 0x0100 214 | SubsystemIdMac SubsystemId = 0x0200 215 | SubsystemIdNwk SubsystemId = 0x0300 216 | SubsystemIdAf SubsystemId = 0x0400 217 | SubsystemIdZdo SubsystemId = 0x0500 218 | SubsystemIdSapi SubsystemId = 0x0600 219 | SubsystemIdUtil SubsystemId = 0x0700 220 | SubsystemIdDebug SubsystemId = 0x0800 221 | SubsystemIdApp SubsystemId = 0x0900 222 | SubsystemIdAllSubsystems SubsystemId = 0xFFFF 223 | ) 224 | 225 | type Action uint8 226 | 227 | const ( 228 | ActionDisable Action = 0 229 | ActionEnable Action = 1 230 | ) 231 | 232 | type Shift uint8 233 | 234 | const ( 235 | ShiftNoShift Shift = 0 236 | ShiftYesShift Shift = 1 237 | ) 238 | 239 | type Mode uint8 240 | 241 | const ( 242 | ModeOFF Mode = 0 243 | ModeON Mode = 1 244 | ) 245 | 246 | type Relation uint8 247 | 248 | const ( 249 | RelationParent Relation = iota 250 | RelationChildRfd 251 | RelationChildRfdRxIdle 252 | RelationChildFfd 253 | RelationChildFfdRxIdle 254 | RelationNeighbor 255 | RelationOther 256 | ) 257 | 258 | type ReqType uint8 259 | 260 | const ( 261 | ReqTypeSingleDeviceResponse ReqType = 0x00 262 | ReqTypeAssociatedDevicesResponse ReqType = 0x01 263 | ) 264 | 265 | type RouteStatus uint8 266 | 267 | const ( 268 | RouteStatusActive RouteStatus = 0x00 269 | RouteStatusDiscoveryUnderway RouteStatus = 0x01 270 | RouteStatusDiscoveryFailed RouteStatus = 0x02 271 | RouteStatusInactive RouteStatus = 0x03 272 | ) 273 | 274 | type Timeout uint8 275 | 276 | const ( 277 | Timeout10Seconds Timeout = 0x00 278 | Timeout2Minutes Timeout = 0x01 279 | Timeout4Minutes Timeout = 0x02 280 | Timeout8Minutes Timeout = 0x03 281 | Timeout16Minutes Timeout = 0x04 282 | Timeout32Minutes Timeout = 0x05 283 | Timeout64Minutes Timeout = 0x06 284 | Timeout128Minutes Timeout = 0x07 285 | Timeout256Minutes Timeout = 0x08 //(Default) 286 | Timeout512Minutes Timeout = 0x09 287 | Timeout1024Minutes Timeout = 0x0A 288 | Timeout2048Minutes Timeout = 0x0B 289 | Timeout4096Minutes Timeout = 0x0C 290 | Timeout8192Minutes Timeout = 0x0D 291 | Timeout16384Minutes Timeout = 0x0E 292 | ) 293 | 294 | type InstallCodeFormat uint8 295 | 296 | const ( 297 | InstallCodeFormatCodePlusCrc InstallCodeFormat = 0x00 298 | InstallCodeFormatKeyDerivedFromInstallCode InstallCodeFormat = 0x01 299 | ) 300 | 301 | type CommissioningMode uint8 302 | 303 | const ( 304 | CommissioningModeInitialization CommissioningMode = 0x00 305 | CommissioningModeTouchLink CommissioningMode = 0x01 306 | CommissioningModeNetworkSteering CommissioningMode = 0x02 307 | CommissioningModeNetworkFormation CommissioningMode = 0x04 308 | CommissioningModeFindingAndBinding CommissioningMode = 0x08 309 | ) 310 | 311 | type CommissioningStatus uint8 312 | 313 | const ( 314 | CommissioningStatusSuccess CommissioningStatus = 0x00 315 | CommissioningStatusInProgress CommissioningStatus = 0x01 316 | CommissioningStatusNoNetwork CommissioningStatus = 0x02 317 | CommissioningStatusTlTargetFailure CommissioningStatus = 0x03 318 | CommissioningStatusTlNotAaCapable CommissioningStatus = 0x04 319 | CommissioningStatusTlNoScanResponse CommissioningStatus = 0x05 320 | CommissioningStatusTlNotPermitted CommissioningStatus = 0x06 321 | CommissioningStatusTclkExFailure CommissioningStatus = 0x07 322 | CommissioningStatusFormationFailure CommissioningStatus = 0x08 323 | CommissioningStatusFbTargetInProgress CommissioningStatus = 0x09 324 | CommissioningStatusFbInitiatorInProgress CommissioningStatus = 0x0A 325 | CommissioningStatusFbNoIdentifyQueryResponse CommissioningStatus = 0x0B 326 | CommissioningStatusFbBindingTableFull CommissioningStatus = 0x0C 327 | CommissioningStatusNetwork CommissioningStatus = 0x0D 328 | ) 329 | 330 | type LqiDeviceType uint8 331 | 332 | const ( 333 | LqiDeviceTypeCoordinator LqiDeviceType = 0x00 334 | LqiDeviceTypeRouter LqiDeviceType = 0x01 335 | LqiDeviceTypeEndDevice LqiDeviceType = 0x02 336 | ) 337 | 338 | type GpAction uint8 339 | 340 | const ( 341 | GpActionAddGPDFIntoQueue GpAction = 0x00 342 | GpActionRemoveGPDFFromQueue GpAction = 0x01 343 | ) 344 | 345 | type GpStatus uint8 346 | 347 | const ( 348 | GpStatusDropFrame GpStatus = 0x00 349 | GpStatusMatch GpStatus = 0x01 350 | GpStatusPassUnprocessed GpStatus = 0x02 351 | GpStatusTxThenDrop GpStatus = 0x03 352 | GpStatusError GpStatus = 0x04 353 | ) 354 | 355 | type GpDataIndStatus uint8 356 | 357 | const ( 358 | GpDataIndStatusSecuritySuccess GpDataIndStatus = 0x00 359 | GpDataIndStatusNoSecurity GpDataIndStatus = 0x01 360 | GpDataIndStatusCounterFailure GpDataIndStatus = 0x02 361 | GpDataIndStatusAuthFailure GpDataIndStatus = 0x03 362 | GpDataIndStatusUnprocessed GpDataIndStatus = 0x04 363 | ) 364 | 365 | const ( 366 | ZbBindingAddr = "0xFFFE" 367 | ZbBroadcastAddr = "0xFFFF" 368 | ) 369 | 370 | const ( 371 | InvalidNodeAddr = "0xFFFE" 372 | ) 373 | 374 | type LogicalType uint8 375 | 376 | const ( 377 | LogicalTypeCoordinator LogicalType = 0 378 | LogicalTypeRouter LogicalType = 1 379 | LogicalTypeeEndDevice LogicalType = 2 380 | ) 381 | -------------------------------------------------------------------------------- /const_strings.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type Status,LatencyReq,DeviceState -output const_strings.go"; DO NOT EDIT. 2 | 3 | package znp 4 | 5 | import "strconv" 6 | 7 | const _Latency_name = "LatencyNoLatencyLatencyFastBeaconsLatencySlowBeacons" 8 | 9 | var _Latency_index = [...]uint8{0, 16, 34, 52} 10 | 11 | func (i Latency) String() string { 12 | if i >= Latency(len(_Latency_index)-1) { 13 | return "Latency(" + strconv.FormatInt(int64(i), 10) + ")" 14 | } 15 | return _Latency_name[_Latency_index[i]:_Latency_index[i+1]] 16 | } 17 | 18 | const _StartupFromAppStatus_name = "StartupFromAppStatusRestoredNetworkStateStartupFromAppStatusNewNetworkStateStartupFromAppStatusLeaveAndNotStarted" 19 | 20 | var _StartupFromAppStatus_index = [...]uint8{0, 40, 75, 113} 21 | 22 | func (i StartupFromAppStatus) String() string { 23 | if i >= StartupFromAppStatus(len(_StartupFromAppStatus_index)-1) { 24 | return "StartupFromAppStatus(" + strconv.FormatInt(int64(i), 10) + ")" 25 | } 26 | return _StartupFromAppStatus_name[_StartupFromAppStatus_index[i]:_StartupFromAppStatus_index[i+1]] 27 | } 28 | 29 | const _Status_name = "StatusSuccessStatusFailureStatusInvalidParameterStatusItemCreatedAndInitializedStatusInitializationFailedStatusBadLengthStatusMemErrorStatusBufferFullStatusUnsupportedModeStatusMacMemErrorStatusSapiInProgressStatusSapiTimeoutStatusSapiInitStatusNotAuthorizedStatusMalformedCmdStatusUnsupClusterCmdStatusZdpInvalidEpStatusZdpNotActiveStatusZdpNotSupportedStatusZdpTimeoutStatusZdpNoMatchStatusZdpNoEntryStatusZdpNoDescriptorStatusZdpInsufficientSpaceStatusZdpNotPermittedStatusZdpTableFullStatusZdpNotAuthorizedStatusZdpBindingTableFullStatusOtaAbortStatusOtaImageInvalidStatusOtaWaitForDataStatusOtaNoImageAvailableStatusOtaRequireMoreImageStatusSecNoKeyStatusSecOldFrmCountStatusSecMaxFrmCountStatusSecCcmFailStatusSecFailureStatusApsFailStatusApsTableFullStatusApsIllegalRequestStatusApsInvalidBindingStatusApsUnsupportedAttribStatusApsNotSupportedStatusApsNoAckStatusApsDuplicateEntryStatusApsNoBoundDeviceStatusApsNotAllowedStatusApsNotAuthenticatedStatusNwkInvalidParamStatusNwkInvalidRequestStatusNwkNotPermittedStatusNwkStartupFailureStatusNwkAlreadyPresentStatusNwkSyncFailureStatusNwkTableFullStatusNwkUnknownDeviceStatusNwkUnsupportedAttributeStatusNwkNoNetworksStatusNwkLeaveUnconfirmedStatusNwkNoAckStatusNwkNoRouteStatusMacBeaconLossStatusMacChannelAccessFailureStatusMacDeniedStatusMacDisableTrxFailureStatusMacFailedSecurityCheckStatusMacFrameTooLongStatusMacInvalidGTSStatusMacInvalidHandleStatusMacInvalidParameterStatusMacNoACKStatusMacNoBeaconStatusMacNoDataStatusMacNoShortAddrStatusMacOutOfCapStatusMacPANIDConflictStatusMacRealignmentStatusMacTransactionExpiredStatusMacTransactionOverFlowStatusMacTxActiveStatusMacUnAvailableKeyStatusMacUnsupportedAttributeStatusMacUnsupportedStatusMacSrcMatchInvalidIndex" 30 | 31 | var _Status_map = map[Status]string{ 32 | 0: _Status_name[0:13], 33 | 1: _Status_name[13:26], 34 | 2: _Status_name[26:48], 35 | 9: _Status_name[48:79], 36 | 10: _Status_name[79:105], 37 | 12: _Status_name[105:120], 38 | 16: _Status_name[120:134], 39 | 17: _Status_name[134:150], 40 | 18: _Status_name[150:171], 41 | 19: _Status_name[171:188], 42 | 32: _Status_name[188:208], 43 | 33: _Status_name[208:225], 44 | 34: _Status_name[225:239], 45 | 126: _Status_name[239:258], 46 | 128: _Status_name[258:276], 47 | 129: _Status_name[276:297], 48 | 130: _Status_name[297:315], 49 | 131: _Status_name[315:333], 50 | 132: _Status_name[333:354], 51 | 133: _Status_name[354:370], 52 | 134: _Status_name[370:386], 53 | 136: _Status_name[386:402], 54 | 137: _Status_name[402:423], 55 | 138: _Status_name[423:449], 56 | 139: _Status_name[449:470], 57 | 140: _Status_name[470:488], 58 | 141: _Status_name[488:510], 59 | 142: _Status_name[510:535], 60 | 149: _Status_name[535:549], 61 | 150: _Status_name[549:570], 62 | 151: _Status_name[570:590], 63 | 152: _Status_name[590:615], 64 | 153: _Status_name[615:640], 65 | 161: _Status_name[640:654], 66 | 162: _Status_name[654:674], 67 | 163: _Status_name[674:694], 68 | 164: _Status_name[694:710], 69 | 173: _Status_name[710:726], 70 | 177: _Status_name[726:739], 71 | 178: _Status_name[739:757], 72 | 179: _Status_name[757:780], 73 | 180: _Status_name[780:803], 74 | 181: _Status_name[803:829], 75 | 182: _Status_name[829:850], 76 | 183: _Status_name[850:864], 77 | 184: _Status_name[864:887], 78 | 185: _Status_name[887:909], 79 | 186: _Status_name[909:928], 80 | 187: _Status_name[928:953], 81 | 193: _Status_name[953:974], 82 | 194: _Status_name[974:997], 83 | 195: _Status_name[997:1018], 84 | 196: _Status_name[1018:1041], 85 | 197: _Status_name[1041:1064], 86 | 198: _Status_name[1064:1084], 87 | 199: _Status_name[1084:1102], 88 | 200: _Status_name[1102:1124], 89 | 201: _Status_name[1124:1153], 90 | 202: _Status_name[1153:1172], 91 | 203: _Status_name[1172:1197], 92 | 204: _Status_name[1197:1211], 93 | 205: _Status_name[1211:1227], 94 | 224: _Status_name[1227:1246], 95 | 225: _Status_name[1246:1275], 96 | 226: _Status_name[1275:1290], 97 | 227: _Status_name[1290:1316], 98 | 228: _Status_name[1316:1344], 99 | 229: _Status_name[1344:1365], 100 | 230: _Status_name[1365:1384], 101 | 231: _Status_name[1384:1406], 102 | 232: _Status_name[1406:1431], 103 | 233: _Status_name[1431:1445], 104 | 234: _Status_name[1445:1462], 105 | 235: _Status_name[1462:1477], 106 | 236: _Status_name[1477:1497], 107 | 237: _Status_name[1497:1514], 108 | 238: _Status_name[1514:1536], 109 | 239: _Status_name[1536:1556], 110 | 240: _Status_name[1556:1583], 111 | 241: _Status_name[1583:1611], 112 | 242: _Status_name[1611:1628], 113 | 243: _Status_name[1628:1651], 114 | 244: _Status_name[1651:1680], 115 | 245: _Status_name[1680:1700], 116 | 255: _Status_name[1700:1729], 117 | } 118 | 119 | func (i Status) String() string { 120 | if str, ok := _Status_map[i]; ok { 121 | return str 122 | } 123 | return "Status(" + strconv.FormatInt(int64(i), 10) + ")" 124 | } 125 | 126 | const ( 127 | _AddrMode_name_0 = "AddrModeAddrNotPresentAddrModeAddrGroupAddrModeAddr16BitAddrModeAddr64Bit" 128 | _AddrMode_name_1 = "AddrModeAddrBroadcast" 129 | ) 130 | 131 | var ( 132 | _AddrMode_index_0 = [...]uint8{0, 22, 39, 56, 73} 133 | ) 134 | 135 | func (i AddrMode) String() string { 136 | switch { 137 | case 0 <= i && i <= 3: 138 | return _AddrMode_name_0[_AddrMode_index_0[i]:_AddrMode_index_0[i+1]] 139 | case i == 15: 140 | return _AddrMode_name_1 141 | default: 142 | return "AddrMode(" + strconv.FormatInt(int64(i), 10) + ")" 143 | } 144 | } 145 | 146 | const _InterPanCommand_name = "InterPanCommandInterPanClrInterPanCommandInterPanSetInterPanCommandInterPanRegInterPanCommandInterPanChk" 147 | 148 | var _InterPanCommand_index = [...]uint8{0, 26, 52, 78, 104} 149 | 150 | func (i InterPanCommand) String() string { 151 | if i >= InterPanCommand(len(_InterPanCommand_index)-1) { 152 | return "InterPanCommand(" + strconv.FormatInt(int64(i), 10) + ")" 153 | } 154 | return _InterPanCommand_name[_InterPanCommand_index[i]:_InterPanCommand_index[i+1]] 155 | } 156 | 157 | const ( 158 | _Channel_name_0 = "ChannelAIN0ChannelAIN1ChannelAIN2ChannelAIN3ChannelAIN4ChannelAIN5ChannelAIN6ChannelAIN7" 159 | _Channel_name_1 = "ChannelTemperatureSensorChannelVoltageReading" 160 | ) 161 | 162 | var ( 163 | _Channel_index_0 = [...]uint8{0, 11, 22, 33, 44, 55, 66, 77, 88} 164 | _Channel_index_1 = [...]uint8{0, 24, 45} 165 | ) 166 | 167 | func (i Channel) String() string { 168 | switch { 169 | case 0 <= i && i <= 7: 170 | return _Channel_name_0[_Channel_index_0[i]:_Channel_index_0[i+1]] 171 | case 22 <= i && i <= 23: 172 | i -= 22 173 | return _Channel_name_1[_Channel_index_1[i]:_Channel_index_1[i+1]] 174 | default: 175 | return "Channel(" + strconv.FormatInt(int64(i), 10) + ")" 176 | } 177 | } 178 | 179 | const _Resolution_name = "Resolution8BitResolution10BitResolution12BitResolution14Bit" 180 | 181 | var _Resolution_index = [...]uint8{0, 14, 29, 44, 59} 182 | 183 | func (i Resolution) String() string { 184 | if i >= Resolution(len(_Resolution_index)-1) { 185 | return "Resolution(" + strconv.FormatInt(int64(i), 10) + ")" 186 | } 187 | return _Resolution_name[_Resolution_index[i]:_Resolution_index[i+1]] 188 | } 189 | 190 | const _Operation_name = "OperationSetDirectionOperationSetInputModeOperationSetOperationClearOperationToggleOperationRead" 191 | 192 | var _Operation_index = [...]uint8{0, 21, 42, 54, 68, 83, 96} 193 | 194 | func (i Operation) String() string { 195 | if i >= Operation(len(_Operation_index)-1) { 196 | return "Operation(" + strconv.FormatInt(int64(i), 10) + ")" 197 | } 198 | return _Operation_name[_Operation_index[i]:_Operation_index[i+1]] 199 | } 200 | 201 | const _Reason_name = "ReasonPowerUpReasonExternalReasonWatchDog" 202 | 203 | var _Reason_index = [...]uint8{0, 13, 27, 41} 204 | 205 | func (i Reason) String() string { 206 | if i >= Reason(len(_Reason_index)-1) { 207 | return "Reason(" + strconv.FormatInt(int64(i), 10) + ")" 208 | } 209 | return _Reason_name[_Reason_index[i]:_Reason_index[i+1]] 210 | } 211 | 212 | const _DeviceState_name = "DeviceStateInitializedNotStartedAutomaticallyDeviceStateInitializedNotConnectedToAnythingDeviceStateDiscoveringPANsToJoinDeviceStateJoiningPANDeviceStateRejoiningPANDeviceStateJoinedButNotAuthenticatedDeviceStateStartedAsDeviceAfterAuthenticationDeviceStateDeviceJoinedAuthenticatedAndIsRouterDeviceStateStartingAsZigBeeCoordinatorDeviceStateStartedAsZigBeeCoordinatorDeviceStateDeviceHasLostInformationAboutItsParentDeviceStateDeviceSendingKeepAliveToParentDeviceStateDeviceWaitingBeforeRejoinDeviceStateReJoiningPANInSecureModeScanningAllChannelsDeviceStateReJoiningPANInTrustCenterModeScanningCurrentChannelDeviceStateReJoiningPANInTrustCenterModeScanningAllChannels" 213 | 214 | var _DeviceState_index = [...]uint16{0, 45, 89, 121, 142, 165, 201, 246, 293, 331, 368, 417, 458, 494, 548, 610, 669} 215 | 216 | func (i DeviceState) String() string { 217 | if i >= DeviceState(len(_DeviceState_index)-1) { 218 | return "DeviceState(" + strconv.FormatInt(int64(i), 10) + ")" 219 | } 220 | return _DeviceState_name[_DeviceState_index[i]:_DeviceState_index[i+1]] 221 | } 222 | 223 | const ( 224 | _SubsystemId_name_0 = "SubsystemIdSys" 225 | _SubsystemId_name_1 = "SubsystemIdMac" 226 | _SubsystemId_name_2 = "SubsystemIdNwk" 227 | _SubsystemId_name_3 = "SubsystemIdAf" 228 | _SubsystemId_name_4 = "SubsystemIdZdo" 229 | _SubsystemId_name_5 = "SubsystemIdSapi" 230 | _SubsystemId_name_6 = "SubsystemIdUtil" 231 | _SubsystemId_name_7 = "SubsystemIdDebug" 232 | _SubsystemId_name_8 = "SubsystemIdApp" 233 | _SubsystemId_name_9 = "SubsystemIdAllSubsystems" 234 | ) 235 | 236 | func (i SubsystemId) String() string { 237 | switch { 238 | case i == 256: 239 | return _SubsystemId_name_0 240 | case i == 512: 241 | return _SubsystemId_name_1 242 | case i == 768: 243 | return _SubsystemId_name_2 244 | case i == 1024: 245 | return _SubsystemId_name_3 246 | case i == 1280: 247 | return _SubsystemId_name_4 248 | case i == 1536: 249 | return _SubsystemId_name_5 250 | case i == 1792: 251 | return _SubsystemId_name_6 252 | case i == 2048: 253 | return _SubsystemId_name_7 254 | case i == 2304: 255 | return _SubsystemId_name_8 256 | case i == 65535: 257 | return _SubsystemId_name_9 258 | default: 259 | return "SubsystemId(" + strconv.FormatInt(int64(i), 10) + ")" 260 | } 261 | } 262 | 263 | const _Action_name = "ActionDisableActionEnable" 264 | 265 | var _Action_index = [...]uint8{0, 13, 25} 266 | 267 | func (i Action) String() string { 268 | if i >= Action(len(_Action_index)-1) { 269 | return "Action(" + strconv.FormatInt(int64(i), 10) + ")" 270 | } 271 | return _Action_name[_Action_index[i]:_Action_index[i+1]] 272 | } 273 | 274 | const _Shift_name = "ShiftNoShiftShiftYesShift" 275 | 276 | var _Shift_index = [...]uint8{0, 12, 25} 277 | 278 | func (i Shift) String() string { 279 | if i >= Shift(len(_Shift_index)-1) { 280 | return "Shift(" + strconv.FormatInt(int64(i), 10) + ")" 281 | } 282 | return _Shift_name[_Shift_index[i]:_Shift_index[i+1]] 283 | } 284 | 285 | const _Mode_name = "ModeOFFModeON" 286 | 287 | var _Mode_index = [...]uint8{0, 7, 13} 288 | 289 | func (i Mode) String() string { 290 | if i >= Mode(len(_Mode_index)-1) { 291 | return "Mode(" + strconv.FormatInt(int64(i), 10) + ")" 292 | } 293 | return _Mode_name[_Mode_index[i]:_Mode_index[i+1]] 294 | } 295 | 296 | const _Relation_name = "RelationParentRelationChildRfdRelationChildRfdRxIdleRelationChildFfdRelationChildFfdRxIdleRelationNeighborRelationOther" 297 | 298 | var _Relation_index = [...]uint8{0, 14, 30, 52, 68, 90, 106, 119} 299 | 300 | func (i Relation) String() string { 301 | if i >= Relation(len(_Relation_index)-1) { 302 | return "Relation(" + strconv.FormatInt(int64(i), 10) + ")" 303 | } 304 | return _Relation_name[_Relation_index[i]:_Relation_index[i+1]] 305 | } 306 | 307 | const _ReqType_name = "ReqTypeSingleDeviceResponseReqTypeAssociatedDevicesResponse" 308 | 309 | var _ReqType_index = [...]uint8{0, 27, 59} 310 | 311 | func (i ReqType) String() string { 312 | if i >= ReqType(len(_ReqType_index)-1) { 313 | return "ReqType(" + strconv.FormatInt(int64(i), 10) + ")" 314 | } 315 | return _ReqType_name[_ReqType_index[i]:_ReqType_index[i+1]] 316 | } 317 | 318 | const _RouteStatus_name = "RouteStatusActiveRouteStatusDiscoveryUnderwayRouteStatusDiscoveryFailedRouteStatusInactive" 319 | 320 | var _RouteStatus_index = [...]uint8{0, 17, 45, 71, 90} 321 | 322 | func (i RouteStatus) String() string { 323 | if i >= RouteStatus(len(_RouteStatus_index)-1) { 324 | return "RouteStatus(" + strconv.FormatInt(int64(i), 10) + ")" 325 | } 326 | return _RouteStatus_name[_RouteStatus_index[i]:_RouteStatus_index[i+1]] 327 | } 328 | 329 | const _Timeout_name = "Timeout10SecondsTimeout2MinutesTimeout4MinutesTimeout8MinutesTimeout16MinutesTimeout32MinutesTimeout64MinutesTimeout128MinutesTimeout256MinutesTimeout512MinutesTimeout1024MinutesTimeout2048MinutesTimeout4096MinutesTimeout8192MinutesTimeout16384Minutes" 330 | 331 | var _Timeout_index = [...]uint8{0, 16, 31, 46, 61, 77, 93, 109, 126, 143, 160, 178, 196, 214, 232, 251} 332 | 333 | func (i Timeout) String() string { 334 | if i >= Timeout(len(_Timeout_index)-1) { 335 | return "Timeout(" + strconv.FormatInt(int64(i), 10) + ")" 336 | } 337 | return _Timeout_name[_Timeout_index[i]:_Timeout_index[i+1]] 338 | } 339 | 340 | const _InstallCodeFormat_name = "InstallCodeFormatCodePlusCrcInstallCodeFormatKeyDerivedFromInstallCode" 341 | 342 | var _InstallCodeFormat_index = [...]uint8{0, 28, 70} 343 | 344 | func (i InstallCodeFormat) String() string { 345 | if i >= InstallCodeFormat(len(_InstallCodeFormat_index)-1) { 346 | return "InstallCodeFormat(" + strconv.FormatInt(int64(i), 10) + ")" 347 | } 348 | return _InstallCodeFormat_name[_InstallCodeFormat_index[i]:_InstallCodeFormat_index[i+1]] 349 | } 350 | 351 | const _CommissioningStatus_name = "CommissioningStatusSuccessCommissioningStatusInProgressCommissioningStatusNoNetworkCommissioningStatusTlTargetFailureCommissioningStatusTlNotAaCapableCommissioningStatusTlNoScanResponseCommissioningStatusTlNotPermittedCommissioningStatusTclkExFailureCommissioningStatusFormationFailureCommissioningStatusFbTargetInProgressCommissioningStatusFbInitiatorInProgressCommissioningStatusFbNoIdentifyQueryResponseCommissioningStatusFbBindingTableFullCommissioningStatusNetwork" 352 | 353 | var _CommissioningStatus_index = [...]uint16{0, 26, 55, 83, 117, 150, 185, 218, 250, 285, 322, 362, 406, 443, 469} 354 | 355 | func (i CommissioningStatus) String() string { 356 | if i >= CommissioningStatus(len(_CommissioningStatus_index)-1) { 357 | return "CommissioningStatus(" + strconv.FormatInt(int64(i), 10) + ")" 358 | } 359 | return _CommissioningStatus_name[_CommissioningStatus_index[i]:_CommissioningStatus_index[i+1]] 360 | } 361 | 362 | const ( 363 | _CommissioningMode_name_0 = "CommissioningModeInitializationCommissioningModeTouchLinkCommissioningModeNetworkSteering" 364 | _CommissioningMode_name_1 = "CommissioningModeNetworkFormation" 365 | _CommissioningMode_name_2 = "CommissioningModeFindingAndBinding" 366 | ) 367 | 368 | var ( 369 | _CommissioningMode_index_0 = [...]uint8{0, 31, 57, 89} 370 | ) 371 | 372 | func (i CommissioningMode) String() string { 373 | switch { 374 | case 0 <= i && i <= 2: 375 | return _CommissioningMode_name_0[_CommissioningMode_index_0[i]:_CommissioningMode_index_0[i+1]] 376 | case i == 4: 377 | return _CommissioningMode_name_1 378 | case i == 8: 379 | return _CommissioningMode_name_2 380 | default: 381 | return "CommissioningMode(" + strconv.FormatInt(int64(i), 10) + ")" 382 | } 383 | } 384 | 385 | const _LqiDeviceType_name = "LqiDeviceTypeCoordinatorLqiDeviceTypeRouterLqiDeviceTypeEndDevice" 386 | 387 | var _LqiDeviceType_index = [...]uint8{0, 24, 43, 65} 388 | 389 | func (i LqiDeviceType) String() string { 390 | if i >= LqiDeviceType(len(_LqiDeviceType_index)-1) { 391 | return "LqiDeviceType(" + strconv.FormatInt(int64(i), 10) + ")" 392 | } 393 | return _LqiDeviceType_name[_LqiDeviceType_index[i]:_LqiDeviceType_index[i+1]] 394 | } 395 | 396 | const _GpAction_name = "GpActionAddGPDFIntoQueueGpActionRemoveGPDFFromQueue" 397 | 398 | var _GpAction_index = [...]uint8{0, 24, 51} 399 | 400 | func (i GpAction) String() string { 401 | if i >= GpAction(len(_GpAction_index)-1) { 402 | return "GpAction(" + strconv.FormatInt(int64(i), 10) + ")" 403 | } 404 | return _GpAction_name[_GpAction_index[i]:_GpAction_index[i+1]] 405 | } 406 | 407 | const _GpStatus_name = "GpStatusDropFrameGpStatusMatchGpStatusPassUnprocessedGpStatusTxThenDropGpStatusError" 408 | 409 | var _GpStatus_index = [...]uint8{0, 17, 30, 53, 71, 84} 410 | 411 | func (i GpStatus) String() string { 412 | if i >= GpStatus(len(_GpStatus_index)-1) { 413 | return "GpStatus(" + strconv.FormatInt(int64(i), 10) + ")" 414 | } 415 | return _GpStatus_name[_GpStatus_index[i]:_GpStatus_index[i+1]] 416 | } 417 | 418 | const _GpDataIndStatus_name = "GpDataIndStatusSecuritySuccessGpDataIndStatusNoSecurityGpDataIndStatusCounterFailureGpDataIndStatusAuthFailureGpDataIndStatusUnprocessed" 419 | 420 | var _GpDataIndStatus_index = [...]uint8{0, 30, 55, 84, 110, 136} 421 | 422 | func (i GpDataIndStatus) String() string { 423 | if i >= GpDataIndStatus(len(_GpDataIndStatus_index)-1) { 424 | return "GpDataIndStatus(" + strconv.FormatInt(int64(i), 10) + ")" 425 | } 426 | return _GpDataIndStatus_name[_GpDataIndStatus_index[i]:_GpDataIndStatus_index[i+1]] 427 | } 428 | 429 | const _LogicalType_name = "LogicalTypeCoordinatorLogicalTypeRouterLogicalTypeeEndDevice" 430 | 431 | var _LogicalType_index = [...]uint8{0, 22, 39, 60} 432 | 433 | func (i LogicalType) String() string { 434 | if i >= LogicalType(len(_LogicalType_index)-1) { 435 | return "LogicalType(" + strconv.FormatInt(int64(i), 10) + ")" 436 | } 437 | return _LogicalType_name[_LogicalType_index[i]:_LogicalType_index[i+1]] 438 | } 439 | -------------------------------------------------------------------------------- /example/example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | "github.com/davecgh/go-spew/spew" 9 | "github.com/dyrkin/unp-go" 10 | "github.com/dyrkin/znp-go" 11 | "go.bug.st/serial.v1" 12 | ) 13 | 14 | func main() { 15 | spew.Config.DisableCapacities = true 16 | spew.Config.DisablePointerAddresses = true 17 | mode := &serial.Mode{ 18 | BaudRate: 115200, 19 | } 20 | 21 | port, err := serial.Open("/dev/tty.usbmodem14101", mode) 22 | if err != nil { 23 | log.Fatalf("Can't open port. Reason: %s", err) 24 | } 25 | port.SetRTS(true) 26 | 27 | u := unp.New(1, port) 28 | z := znp.New(u) 29 | z.Start() 30 | 31 | go func() { 32 | for { 33 | select { 34 | case err := <-z.Errors(): 35 | fmt.Printf("Error received: %s\n", err) 36 | case async := <-z.AsyncInbound(): 37 | fmt.Printf("Async received: %s\n", spew.Sdump(async)) 38 | } 39 | } 40 | }() 41 | 42 | go func() { 43 | for { 44 | select { 45 | case frame := <-z.OutFramesLog(): 46 | fmt.Printf("Frame sent: %s\n", spew.Sdump(frame)) 47 | case frame := <-z.InFramesLog(): 48 | fmt.Printf("Frame received: %s\n", spew.Sdump(frame)) 49 | } 50 | } 51 | }() 52 | 53 | // z.SysResetReq(1) 54 | 55 | var res interface{} 56 | 57 | res, err = z.SysPing() 58 | if err != nil { 59 | log.Fatal(err) 60 | } 61 | PrintStruct(res) 62 | 63 | res, err = z.SysVersion() 64 | if err != nil { 65 | log.Fatal(err) 66 | } 67 | PrintStruct(res) 68 | 69 | res, err = z.SysSetExtAddr("0x00124b00019c2ee9") 70 | if err != nil { 71 | log.Fatal(err) 72 | } 73 | PrintStruct(res) 74 | 75 | res, err = z.UtilCallbackSubCmd(znp.SubsystemIdZdo, znp.ActionEnable) 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | PrintStruct(res) 80 | 81 | res, err = z.SysGetExtAddr() 82 | if err != nil { 83 | log.Fatal(err) 84 | } 85 | PrintStruct(res) 86 | 87 | res, err = z.SapiZbStartRequest() 88 | if err != nil { 89 | log.Fatal(err) 90 | } 91 | PrintStruct(res) 92 | 93 | res, err = z.SapiZbPermitJoiningRequest("0xFF00", 200) 94 | if err != nil { 95 | log.Fatal(err) 96 | } 97 | PrintStruct(res) 98 | 99 | res, err = z.SapiZbReadConfiguration(1) 100 | if err != nil { 101 | log.Fatal(err) 102 | } 103 | PrintStruct(res) 104 | 105 | res, err = z.SapiZbFindDeviceRequest("0x00124b00019c2ee9") 106 | if err != nil { 107 | log.Fatal(err) 108 | } 109 | PrintStruct(res) 110 | 111 | res, err = z.SysOsalStartTimer(1, 3000) 112 | if err != nil { 113 | log.Fatal(err) 114 | } 115 | PrintStruct(res) 116 | 117 | t := time.Now() 118 | 119 | res, err = z.SysSetTime(0, uint8(t.Hour()), uint8(t.Minute()), uint8(t.Second()), uint8(t.Month()), uint8(t.Day()), uint16(t.Year())) 120 | if err != nil { 121 | log.Fatal(err) 122 | } 123 | PrintStruct(res) 124 | 125 | res, err = z.SysGetTime() 126 | if err != nil { 127 | log.Fatal(err) 128 | } 129 | PrintStruct(res) 130 | 131 | res, err = z.UtilGetDeviceInfo() 132 | if err != nil { 133 | log.Fatal(err) 134 | } 135 | PrintStruct(res) 136 | 137 | res, err = z.UtilGetNvInfo() 138 | if err != nil { 139 | log.Fatal(err) 140 | } 141 | PrintStruct(res) 142 | 143 | res, err = z.UtilLoopback([]uint8{1, 2, 3, 4, 5, 6, 7, 8, 9}) 144 | if err != nil { 145 | log.Fatal(err) 146 | } 147 | PrintStruct(res) 148 | 149 | res, err = z.UtilAssocFindDevice(1) 150 | if err != nil { 151 | log.Fatal(err) 152 | } 153 | PrintStruct(res) 154 | 155 | res, err = z.UtilAssocGetWithAddr("0x0000000000000000", "0x25cc") 156 | if err != nil { 157 | log.Fatal(err) 158 | } 159 | PrintStruct(res) 160 | 161 | err = z.UtilSyncReq() 162 | if err != nil { 163 | log.Fatal(err) 164 | } 165 | 166 | res, err = z.ZdoNwkAddrReq("0x00124b00019c2ee9", znp.ReqTypeAssociatedDevicesResponse, 0) 167 | if err != nil { 168 | log.Fatal(err) 169 | } 170 | PrintStruct(res) 171 | 172 | res, err = z.ZdoIeeeAddrReq("0x25cc", znp.ReqTypeAssociatedDevicesResponse, 0) 173 | if err != nil { 174 | log.Fatal(err) 175 | } 176 | PrintStruct(res) 177 | 178 | res, err = z.ZdoUserDescSet("0x0000", "0x25cc", "hello") 179 | if err != nil { 180 | log.Fatal(err) 181 | } 182 | 183 | res, err = z.ZdoUserDescReq("0x0000", "0xe065") 184 | if err != nil { 185 | log.Fatal(err) 186 | } 187 | PrintStruct(res) 188 | 189 | res, err = z.ZdoServerDiscReq(&znp.ServerMask{PrimTrustCenter: 1}) 190 | if err != nil { 191 | log.Fatal(err) 192 | } 193 | 194 | PrintStruct(res) 195 | 196 | res, err = z.ZdoMgmtNwkDiskReq("0x0000", &znp.Channels{Channel11: 1, Channel12: 1, Channel13: 1, Channel14: 1}, 1, 0) 197 | if err != nil { 198 | log.Fatal(err) 199 | } 200 | 201 | PrintStruct(res) 202 | 203 | res, err = z.ZdoMgmtLqiReq("0x0000", 0) 204 | if err != nil { 205 | log.Fatal(err) 206 | } 207 | 208 | PrintStruct(res) 209 | 210 | res, err = z.ZdoMgmtRtgReq("0x0000", 0) 211 | if err != nil { 212 | log.Fatal(err) 213 | } 214 | 215 | PrintStruct(res) 216 | 217 | // res, err = z.ZdoBindReq("0x0000", "0x00124b00019c2ee9", 1, 30, znp.AddrModeAddr64Bit, "0x0000000000003000", 2) 218 | // if err != nil { 219 | // log.Fatal(err) 220 | // } 221 | 222 | // PrintStruct(res) 223 | 224 | res, err = z.ZdoMgmtPermitJoinReq(znp.AddrModeAddr16Bit, "0x0000", 255, 0) 225 | if err != nil { 226 | log.Fatal(err) 227 | } 228 | 229 | PrintStruct(res) 230 | 231 | res, err = z.ZdoMgmtNwkUpdateReq("0x25cc", znp.AddrModeAddr16Bit, &znp.Channels{Channel11: 1, Channel12: 1, Channel13: 1, Channel14: 1}, 1) 232 | if err != nil { 233 | log.Fatal(err) 234 | } 235 | 236 | PrintStruct(res) 237 | 238 | res, err = z.ZdoMsgCbRegister(1588) 239 | if err != nil { 240 | log.Fatal(err) 241 | } 242 | 243 | PrintStruct(res) 244 | 245 | res, err = z.ZdoStartupFromApp(1) 246 | if err != nil { 247 | log.Fatal(err) 248 | } 249 | 250 | PrintStruct(res) 251 | 252 | res, err = z.ZdoNwkDiscoveryReq(&znp.Channels{Channel11: 1, Channel12: 1, Channel13: 1, Channel14: 1}, 1) 253 | if err != nil { 254 | log.Fatal(err) 255 | } 256 | 257 | PrintStruct(res) 258 | 259 | res, err = z.ZdoExtAddGroup(1, 5, "asdfghjklzxcvbn") 260 | if err != nil { 261 | log.Fatal(err) 262 | } 263 | 264 | PrintStruct(res) 265 | 266 | res, err = z.ZdoExtFindGroup(1, 5) 267 | if err != nil { 268 | log.Fatal(err) 269 | } 270 | 271 | PrintStruct(res) 272 | 273 | res, err = z.ZdoExtFindAllGroupsEndpoint(1, []uint16{5}) 274 | if err != nil { 275 | log.Fatal(err) 276 | } 277 | 278 | PrintStruct(res) 279 | 280 | res, err = z.ZdoExtCountAllGroups() 281 | if err != nil { 282 | log.Fatal(err) 283 | } 284 | 285 | PrintStruct(res) 286 | 287 | res, err = z.ZdoExtSwitchNwkKey("0x25cc", 0) 288 | if err != nil { 289 | log.Fatal(err) 290 | } 291 | 292 | PrintStruct(res) 293 | 294 | res, err = z.UtilGetDeviceInfo() 295 | if err != nil { 296 | log.Fatal(err) 297 | } 298 | 299 | PrintStruct(res) 300 | 301 | res, err = z.ZdoNodeDescReq("0x0000", "0x0000") 302 | if err != nil { 303 | log.Fatal(err) 304 | } 305 | 306 | PrintStruct(res) 307 | 308 | res, err = z.ZdoActiveEpReq("0x0000", "0x0000") 309 | if err != nil { 310 | log.Fatal(err) 311 | } 312 | 313 | PrintStruct(res) 314 | 315 | res, err = z.ZdoPowerDescReq("0x0000", "0x0000") 316 | if err != nil { 317 | log.Fatal(err) 318 | } 319 | 320 | PrintStruct(res) 321 | 322 | res, err = z.ZdoComplexDescReq("0x0000", "0x0000") 323 | if err != nil { 324 | log.Fatal(err) 325 | } 326 | 327 | PrintStruct(res) 328 | 329 | res, err = z.ZdoUserDescReq("0x0000", "0x0000") 330 | if err != nil { 331 | log.Fatal(err) 332 | } 333 | 334 | PrintStruct(res) 335 | 336 | res, err = z.ZdoMgmtLqiReq("0x0000", 0) 337 | if err != nil { 338 | log.Fatal(err) 339 | } 340 | 341 | PrintStruct(res) 342 | 343 | res, err = z.ZdoMgmtRtgReq("0x0000", 0) 344 | if err != nil { 345 | log.Fatal(err) 346 | } 347 | 348 | PrintStruct(res) 349 | 350 | err = z.DebugMsg("hello") 351 | if err != nil { 352 | log.Fatal(err) 353 | } 354 | 355 | res, err = z.ZdoStartupFromApp(30) 356 | if err != nil { 357 | log.Fatal(err) 358 | } 359 | PrintStruct(res) 360 | 361 | z.AfRegister(1, 0x0104, 1, 1, znp.LatencyNoLatency, []uint16{}, []uint16{}) 362 | 363 | res, err = z.ZdoMgmtBindReq("0x0000", 1) 364 | if err != nil { 365 | log.Fatal(err) 366 | } 367 | 368 | PrintStruct(res) 369 | 370 | res, err = z.UtilLedControl(1, znp.ModeOFF) 371 | if err != nil { 372 | log.Fatal(err) 373 | } 374 | PrintStruct(res) 375 | 376 | time.Sleep(200 * time.Second) 377 | } 378 | 379 | func PrintStruct(v interface{}) { 380 | spew.Dump(v) 381 | } 382 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dyrkin/znp-go 2 | 3 | require ( 4 | github.com/davecgh/go-spew v1.1.1 5 | github.com/dyrkin/bin v0.0.0-20190204210718-06bd23f8c0ce 6 | github.com/dyrkin/unp-go v1.0.2 7 | github.com/dyrkin/zcl-go v0.0.0-20190204225456-fc857835ed35 8 | go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 9 | golang.org/x/sys v0.0.0-20190124100055-b90733256f2e 10 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 11 | ) 12 | -------------------------------------------------------------------------------- /model.go: -------------------------------------------------------------------------------- 1 | package znp 2 | 3 | type StatusResponse struct { 4 | Status Status 5 | } 6 | 7 | // =======AF======= 8 | 9 | type AfRegister struct { 10 | EndPoint uint8 11 | AppProfID uint16 12 | AppDeviceID uint16 13 | AddDevVer uint8 14 | LatencyReq Latency 15 | AppInClusterList []uint16 `size:"1"` 16 | AppOutClusterList []uint16 `size:"1"` 17 | } 18 | 19 | type AfDataRequestOptions struct { 20 | WildcardProfileID uint8 `bits:"0b00000010" bitmask:"start" ` 21 | APSAck uint8 `bits:"0b00010000"` 22 | DiscoverRoute uint8 `bits:"0b00100000"` 23 | APSSecurity uint8 `bits:"0b01000000"` 24 | SkipRouting uint8 `bits:"0b10000000" bitmask:"end" ` 25 | } 26 | 27 | type AfDataRequest struct { 28 | DstAddr string `hex:"2"` 29 | DstEndpoint uint8 30 | SrcEndpoint uint8 31 | ClusterID uint16 32 | TransID uint8 33 | Options *AfDataRequestOptions 34 | Radius uint8 35 | Data []uint8 `size:"1"` 36 | } 37 | 38 | type AfDataRequestExt struct { 39 | DstAddrMode AddrMode 40 | DstAddr string `hex:"8"` 41 | DstEndpoint uint8 42 | DstPanID uint16 //PAN - personal area networks 43 | SrcEndpoint uint8 44 | ClusterID uint16 45 | TransID uint8 46 | Options *AfDataRequestOptions 47 | Radius uint8 48 | Data []uint8 `size:"2"` 49 | } 50 | 51 | type AfDataRequestSrcRtgOptions struct { 52 | APSAck uint8 `bits:"0b00000001" bitmask:"start` 53 | APSSecurity uint8 `bits:"0b00000100"` 54 | SkipRouting uint8 `bits:"0b00001000" bitmask:"end" ` 55 | } 56 | 57 | type AfDataRequestSrcRtg struct { 58 | DstAddr string `hex:"2"` 59 | DstEndpoint uint8 60 | SrcEndpoint uint8 61 | ClusterID uint16 62 | TransID uint8 63 | Options *AfDataRequestSrcRtgOptions 64 | Radius uint8 65 | RelayList []string `size:"1" hex:"2"` 66 | Data []uint8 `size:"1"` 67 | } 68 | 69 | type AfInterPanCtlData interface { 70 | AfInterPanCtlData() 71 | } 72 | 73 | type AfInterPanClrData struct{} 74 | 75 | func (a *AfInterPanClrData) AfInterPanCtlData() {} 76 | 77 | type AfInterPanSetData struct { 78 | Channel uint8 79 | } 80 | 81 | func (a *AfInterPanSetData) AfInterPanCtlData() {} 82 | 83 | type AfInterPanRegData struct { 84 | Endpoint uint8 85 | } 86 | 87 | func (a *AfInterPanRegData) AfInterPanCtlData() {} 88 | 89 | type AfInterPanChkData struct { 90 | PanID uint16 91 | Endpoint uint8 92 | } 93 | 94 | func (a *AfInterPanChkData) AfInterPanCtlData() {} 95 | 96 | type AfInterPanCtl struct { 97 | Command InterPanCommand 98 | Data AfInterPanCtlData 99 | } 100 | 101 | type AfDataRetrieve struct { 102 | Timestamp uint32 103 | Index uint16 104 | Length uint8 105 | } 106 | 107 | type AfDataRetrieveResponse struct { 108 | Status StatusResponse 109 | Data []uint8 `size:"1"` 110 | } 111 | 112 | type AfApsfConfigSet struct { 113 | Endpoint uint8 114 | FrameDelay uint8 115 | WindowSize uint8 116 | } 117 | 118 | type AfDataConfirm struct { 119 | Status Status 120 | Endpoint uint8 121 | TransID uint8 122 | } 123 | 124 | type AfReflectError struct { 125 | Status Status 126 | Endpoint uint8 127 | TransID uint8 128 | DstAddrMode AddrMode 129 | DstAddr string `hex:"2"` 130 | } 131 | 132 | type AfIncomingMessage struct { 133 | GroupID uint16 134 | ClusterID uint16 135 | SrcAddr string `hex:"2"` 136 | SrcEndpoint uint8 137 | DstEndpoint uint8 138 | WasBroadcast uint8 139 | LinkQuality uint8 140 | SecurityUse uint8 141 | Timestamp uint32 142 | TransSeqNumber uint8 143 | Data []uint8 `size:"1"` 144 | } 145 | 146 | type AfDataStore struct { 147 | Index uint16 148 | Data []uint8 `size:"1"` 149 | } 150 | 151 | type AfIncomingMessageExt struct { 152 | GroupID uint16 153 | ClusterID uint16 154 | SrcAddrMode AddrMode 155 | SrcAddr string `hex:"8"` 156 | SrcEndpoint uint8 157 | SrcPanID uint16 158 | DstEndpoint uint8 159 | WasBroadcast uint8 160 | LinkQuality uint8 161 | SecurityUse uint8 162 | Timestamp uint32 163 | TransSeqNumber uint8 164 | Data []uint8 `size:"2"` 165 | } 166 | 167 | // =======APP======= 168 | 169 | type AppMsg struct { 170 | AppEndpoint uint8 171 | DstAddr string `hex:"2"` 172 | DstEndpoint uint8 173 | ClusterID uint16 174 | Message []uint8 `size:"1"` 175 | } 176 | 177 | type AppUserTest struct { 178 | SrcEndpoint uint8 179 | CommandID uint16 180 | Parameter1 uint16 181 | Parameter2 uint16 182 | } 183 | 184 | // =======DEBUG======= 185 | 186 | type DebugSetThreshold struct { 187 | ComponentID uint8 188 | Threshold uint8 189 | } 190 | 191 | type DebugMsg struct { 192 | String string `size:"1"` 193 | } 194 | 195 | // =======SAPI======= 196 | 197 | type EmptyResponse struct{} 198 | 199 | type SapiZbPermitJoiningRequest struct { 200 | Destination string `hex:"2"` 201 | Timeout uint8 202 | } 203 | 204 | type SapiZbBindDevice struct { 205 | Create uint8 206 | CommandID uint16 207 | Destination string `hex:"8"` 208 | } 209 | 210 | type SapiZbAllowBind struct { 211 | Timeout uint8 212 | } 213 | 214 | type SapiZbSendDataRequest struct { 215 | Destination string `hex:"2"` 216 | CommandID uint16 217 | Handle uint8 218 | Ack uint8 219 | Radius uint8 220 | Data []uint8 `size:"1"` 221 | } 222 | 223 | type SapiZbReadConfiguration struct { 224 | ConfigID uint8 225 | } 226 | 227 | type SapiZbReadConfigurationResponse struct { 228 | Status Status 229 | ConfigID uint8 230 | Value []uint8 `size:"1"` 231 | } 232 | 233 | type SapiZbWriteConfiguration struct { 234 | ConfigID uint8 235 | Value []uint8 `size:"1"` 236 | } 237 | 238 | type SapiZbGetDeviceInfo struct { 239 | Param uint8 240 | } 241 | 242 | type SapiZbGetDeviceInfoResponse struct { 243 | Param uint8 244 | Value uint16 245 | } 246 | 247 | type SapiZbFindDeviceRequest struct { 248 | SearchKey string `hex:"8"` 249 | } 250 | 251 | type SapiZbStartConfirm struct { 252 | Status Status 253 | } 254 | 255 | type SapiZbBindConfirm struct { 256 | CommandID uint16 257 | Status Status 258 | } 259 | 260 | type SapiZbAllowBindConfirm struct { 261 | Source string `hex:"2"` 262 | } 263 | 264 | type SapiZbSendDataConfirm struct { 265 | Handle uint8 266 | Status Status 267 | } 268 | 269 | type SapiZbReceiveDataIndication struct { 270 | Source string `hex:"2"` 271 | CommandID uint16 272 | Data []uint8 `size:"1"` 273 | } 274 | 275 | type SapiZbFindDeviceConfirm struct { 276 | SearchType uint8 277 | Result string `hex:"2"` 278 | SearchKey string `hex:"8"` 279 | } 280 | 281 | // =======SYS======= 282 | 283 | type SysResetReq struct { 284 | //This command will reset the device by using a hardware reset (i.e. 285 | //watchdog reset) if ‘Type’ is zero. Otherwise a soft reset (i.e. a jump to the 286 | //reset vector) is done. This is especially useful in the CC2531, for 287 | //instance, so that the USB host does not have to contend with the USB 288 | //H/W resetting (and thus causing the USB host to re-enumerate the device 289 | //which can cause an open virtual serial port to hang.) 290 | ResetType byte 291 | } 292 | 293 | //Capabilities represents the interfaces that this device can handle (compiled into the device) 294 | type Capabilities struct { 295 | Sys uint16 `bitmask:"start" bits:"0x0001"` 296 | Mac uint16 `bits:"0x0002"` 297 | Nwk uint16 `bits:"0x0004"` 298 | Af uint16 `bits:"0x0008"` 299 | Zdo uint16 `bits:"0x0010"` 300 | Sapi uint16 `bits:"0x0020"` 301 | Util uint16 `bits:"0x0040"` 302 | Debug uint16 `bits:"0x0080"` 303 | App uint16 `bits:"0x0100"` 304 | Zoad uint16 `bitmask:"end" bits:"0x1000"` 305 | } 306 | 307 | type SysPingResponse struct { 308 | Capabilities *Capabilities 309 | } 310 | 311 | type SysVersionResponse struct { 312 | TransportRev uint8 //Transport protocol revision 313 | Product uint8 //Product Id 314 | MajorRel uint8 //Software major release number 315 | MinorRel uint8 //Software minor release number 316 | MaintRel uint8 //Software maintenance release number 317 | } 318 | 319 | type SysSetExtAddr struct { 320 | ExtAddress string `hex:"8"` //The device’s extended address. 321 | } 322 | 323 | type SysGetExtAddrResponse struct { 324 | ExtAddress string `hex:"8"` //The device’s extended address. 325 | } 326 | 327 | type SysRamRead struct { 328 | Address uint16 //Address of the memory that will be read. 329 | Len uint8 //The number of bytes that will be read from the target RAM. 330 | } 331 | 332 | type SysRamReadResponse struct { 333 | Status uint8 //Status is either Success (0) or Failure (1). 334 | Value []uint8 `size:"1"` //The value read from the target RAM. 335 | } 336 | 337 | type SysRamWrite struct { 338 | Address uint16 //Address of the memory that will be written. 339 | Value []uint8 `size:"1"` //The value written to the target RAM. 340 | } 341 | 342 | type SysOsalNvRead struct { 343 | ID uint16 344 | Offset uint8 345 | } 346 | 347 | type SysOsalNvReadResponse struct { 348 | Status Status 349 | Value []uint8 `size:"1"` 350 | } 351 | 352 | type SysOsalNvWrite struct { 353 | ID uint16 354 | Offset uint8 355 | Value []uint8 `size:"1"` 356 | } 357 | 358 | type SysOsalNvItemInit struct { 359 | ID uint16 360 | ItemLen uint16 361 | InitData []uint8 `size:"1"` 362 | } 363 | 364 | type SysOsalNvDelete struct { 365 | ID uint16 366 | ItemLen uint16 367 | } 368 | 369 | type SysOsalNvLength struct { 370 | ID uint16 371 | } 372 | 373 | type SysOsalNvLengthResponse struct { 374 | Length uint16 375 | } 376 | 377 | type SysOsalStartTimer struct { 378 | ID uint8 379 | Timeout uint16 380 | } 381 | 382 | type SysOsalStopTimer struct { 383 | ID uint8 384 | } 385 | 386 | type SysRandomResponse struct { 387 | Value uint16 388 | } 389 | 390 | type SysAdcRead struct { 391 | Channel Channel 392 | Resolution Resolution 393 | } 394 | 395 | type SysAdcReadResponse struct { 396 | Value uint16 397 | } 398 | 399 | type SysGpio struct { 400 | Operation Operation 401 | Value uint8 402 | } 403 | 404 | type SysGpioResponse struct { 405 | Value uint8 406 | } 407 | 408 | type SysTime struct { 409 | UTCTime uint32 410 | Hour uint8 411 | Minute uint8 412 | Second uint8 413 | Month uint8 414 | Day uint8 415 | Year uint16 416 | } 417 | 418 | type SysSetTxPower struct { 419 | TXPower uint8 420 | } 421 | 422 | type SysSetTxPowerResponse struct { 423 | TXPower uint8 424 | } 425 | 426 | type SysZDiagsClearStats struct { 427 | ClearNV uint8 428 | } 429 | 430 | type SysZDiagsClearStatsResponse struct { 431 | SysClock uint32 432 | } 433 | 434 | type SysZDiagsGetStats struct { 435 | AttributeID uint16 436 | } 437 | 438 | type SysZDiagsGetStatsResponse struct { 439 | AttributeValue uint32 440 | } 441 | 442 | type SysZDiagsSaveStatsToNvResponse struct { 443 | SysClock uint32 444 | } 445 | 446 | type SysNvCreate struct { 447 | SysID uint8 448 | ItemID uint16 449 | SubID uint16 450 | Length uint32 451 | } 452 | 453 | type SysNvDelete struct { 454 | SysID uint8 455 | ItemID uint16 456 | SubID uint16 457 | } 458 | 459 | type SysNvLength struct { 460 | SysID uint8 461 | ItemID uint16 462 | SubID uint16 463 | } 464 | 465 | type SysNvLengthResponse struct { 466 | Length uint8 467 | } 468 | 469 | type SysNvRead struct { 470 | SysID uint8 471 | ItemID uint16 472 | SubID uint16 473 | Offset uint16 474 | Length uint8 475 | } 476 | 477 | type SysNvReadResponse struct { 478 | Status Status 479 | Value []uint8 `size:"1"` 480 | } 481 | 482 | type SysNvWrite struct { 483 | SysID uint8 484 | ItemID uint16 485 | SubID uint16 486 | Offset uint16 487 | Value []uint8 `size:"1"` 488 | } 489 | 490 | type SysNvUpdate struct { 491 | SysID uint8 492 | ItemID uint16 493 | SubID uint16 494 | Value []uint8 `size:"1"` 495 | } 496 | 497 | type SysNvCompact struct { 498 | Threshold uint16 499 | } 500 | 501 | type SysNvReadExt struct { 502 | ID uint16 503 | Offset uint16 504 | } 505 | 506 | type SysNvWriteExt struct { 507 | ID uint16 508 | Offset uint16 509 | Value []uint8 `size:"1"` 510 | } 511 | 512 | type SysResetInd struct { 513 | Reason Reason 514 | TransportRev uint8 515 | Product uint8 516 | MinorRel uint8 517 | HwRev uint8 518 | } 519 | 520 | type SysOsalTimerExpired struct { 521 | ID uint8 522 | } 523 | 524 | // =======UTIL======= 525 | 526 | type DeviceType struct { 527 | Coordinator uint8 `bits:"0x01" bitmask:"start"` 528 | Router uint8 `bits:"0x02"` 529 | EndDevice uint8 `bits:"0x04" bitmask:"end"` 530 | } 531 | 532 | type UtilGetDeviceInfoResponse struct { 533 | Status Status 534 | IEEEAddr string `hex:"8"` 535 | ShortAddr string `hex:"2"` 536 | DeviceType *DeviceType 537 | DeviceState DeviceState 538 | AssocDevicesList []string `size:"1" hex:"2"` 539 | } 540 | 541 | type NvInfoStatus struct { 542 | IEEEAddress Status `bits:"0b00000001" bitmask:"start"` 543 | ScanChannels Status `bits:"0b00000010"` 544 | PanID Status `bits:"0b00000100"` 545 | SecurityLevel Status `bits:"0b00001000"` 546 | PreConfigKey Status `bits:"0b00010000" bitmask:"end"` 547 | } 548 | 549 | type UtilGetNvInfoResponse struct { 550 | Status *NvInfoStatus 551 | IEEEAddr string `hex:"8"` 552 | ScanChannels uint32 553 | PanID uint16 554 | SecurityLevel uint8 555 | PreConfigKey [16]uint8 556 | } 557 | 558 | type UtilSetPanId struct { 559 | PanID uint16 560 | } 561 | 562 | type UtilSetChannels struct { 563 | Channels *Channels 564 | } 565 | 566 | type UtilSetSecLevel struct { 567 | SecLevel uint8 568 | } 569 | 570 | type UtilSetPreCfgKey struct { 571 | PreCfgKey [16]uint8 572 | } 573 | 574 | type UtilCallbackSubCmd struct { 575 | SubsystemID SubsystemId 576 | Action Action 577 | } 578 | 579 | type Keys struct { 580 | Key1 uint8 `bits:"0x01" bitmask:"start"` 581 | Key2 uint8 `bits:"0x02"` 582 | Key3 uint8 `bits:"0x04"` 583 | Key4 uint8 `bits:"0x08"` 584 | Key5 uint8 `bits:"0x10"` 585 | Key6 uint8 `bits:"0x20"` 586 | Key7 uint8 `bits:"0x40"` 587 | Key8 uint8 `bits:"0x80" bitmask:"end"` 588 | } 589 | 590 | type UtilKeyEvent struct { 591 | Keys *Keys 592 | Shift Shift 593 | } 594 | 595 | type UtilTimeAliveResponse struct { 596 | Seconds uint32 597 | } 598 | 599 | type UtilLedControl struct { 600 | LedID uint8 601 | Mode Mode 602 | } 603 | 604 | type UtilLoopback struct { 605 | Data []uint8 606 | } 607 | 608 | type UtilDataReq struct { 609 | SecurityUse uint8 610 | } 611 | 612 | type UtilSrcMatchAddEntry struct { 613 | AddrMode AddrMode 614 | Address string `hex:"8"` 615 | PanID uint16 616 | } 617 | 618 | type UtilSrcMatchDelEntry struct { 619 | AddrMode AddrMode 620 | Address string `hex:"8"` 621 | PanID uint16 622 | } 623 | 624 | type UtilSrcMatchCheckSrcAddr struct { 625 | AddrMode AddrMode 626 | Address string `hex:"8"` 627 | PanID uint16 628 | } 629 | 630 | type UtilSrcMatchAckAllPending struct { 631 | Option Action 632 | } 633 | 634 | type UtilSrcMatchCheckAllPendingResponse struct { 635 | Status Status 636 | Value uint8 637 | } 638 | 639 | type UtilAddrMgrExtAddrLookup struct { 640 | ExtAddr string `hex:"8"` 641 | } 642 | 643 | type UtilAddrMgrExtAddrLookupResponse struct { 644 | NwkAddr string `hex:"2"` 645 | } 646 | 647 | type UtilAddrMgrAddrLookup struct { 648 | NwkAddr string `hex:"2"` 649 | } 650 | 651 | type UtilAddrMgrAddrLookupResponse struct { 652 | ExtAddr string `hex:"8"` 653 | } 654 | 655 | type UtilApsmeLinkKeyDataGet struct { 656 | ExtAddr string `hex:"8"` 657 | } 658 | 659 | type UtilApsmeLinkKeyDataGetResponse struct { 660 | Status Status 661 | SecKey [16]uint8 662 | TxFrmCntr uint32 663 | RxFrmCntr uint32 664 | } 665 | 666 | type UtilApsmeLinkKeyNvIdGet struct { 667 | ExtAddr string `hex:"8"` 668 | } 669 | 670 | type UtilApsmeLinkKeyNvIdGetResponse struct { 671 | Status Status 672 | LinkKeyNvId uint16 673 | } 674 | 675 | type UtilApsmeRequestKeyCmd struct { 676 | PartnerAddr string `hex:"8"` 677 | } 678 | 679 | type UtilAssocCount struct { 680 | StartRelation Relation 681 | EndRelation Relation 682 | } 683 | 684 | type UtilAssocCountResponse struct { 685 | Count uint16 686 | } 687 | 688 | type LinkInfo struct { 689 | TxCounter uint8 // Counter of transmission success/failures 690 | TxCost uint8 // Average of sending rssi values if link staus is enabled 691 | // i.e. NWK_LINK_STATUS_PERIOD is defined as non zero 692 | RxLqi uint8 // average of received rssi values 693 | // needs to be converted to link cost (1-7) before used 694 | InKeySeqNum uint8 // security key sequence number 695 | InFrmCntr uint32 // security frame counter.. 696 | TxFailure uint16 // higher values indicate more failures 697 | } 698 | 699 | type AgingEndDevice struct { 700 | EndDevCfg uint8 701 | DeviceTimeout uint32 702 | } 703 | 704 | type Device struct { 705 | ShortAddr string `hex:"2"` // Short address of associated device, or invalid 0xfffe 706 | AddrIdx uint16 // Index from the address manager 707 | NodeRelation uint8 708 | DevStatus uint8 // bitmap of various status values 709 | AssocCnt uint8 710 | Age uint8 711 | LinkInfo *LinkInfo 712 | EndDev *AgingEndDevice 713 | TimeoutCounter uint32 714 | KeepaliveRcv uint8 715 | } 716 | 717 | type UtilAssocFindDevice struct { 718 | Number uint8 719 | } 720 | 721 | type UtilAssocFindDeviceResponse struct { 722 | Device *Device 723 | } 724 | 725 | type UtilAssocGetWithAddr struct { 726 | ExtAddr string `hex:"8"` 727 | NwkAddr string `hex:"2"` 728 | } 729 | 730 | type UtilAssocGetWithAddrResponse struct { 731 | Device *Device 732 | } 733 | 734 | type UtilBindAddEntry struct { 735 | AddrMode AddrMode 736 | DstAddr string `hex:"8"` 737 | DstEndpoint uint8 738 | ClusterIDs []uint16 `size:"1"` 739 | } 740 | 741 | type BindEntry struct { 742 | SrcEP uint8 743 | DstGroupMode uint8 744 | DstIdx uint16 745 | DstEP uint8 746 | ClusterIDList []uint16 `size:"1"` 747 | } 748 | 749 | type UtilBindAddEntryResponse struct { 750 | BindEntry *BindEntry 751 | } 752 | 753 | type UtilZclKeyEstInitEst struct { 754 | TaskID uint8 755 | SeqNum uint8 756 | EndPoint uint8 757 | AddrMode AddrMode 758 | Addr string `hex:"8"` 759 | } 760 | 761 | type UtilZclKeyEstSign struct { 762 | Input []uint8 `size:"1"` 763 | } 764 | 765 | type UtilZclKeyEstSignResponse struct { 766 | Status Status 767 | Key [42]uint8 768 | } 769 | 770 | type UtilSrngGenResponse struct { 771 | SecureRandomNumbers [100]uint8 772 | } 773 | 774 | type UtilSyncReq struct{} 775 | 776 | type UtilZclKeyEstablishInd struct { 777 | TaskId uint8 778 | Event uint8 779 | Status uint8 780 | WaitTime uint8 781 | Suite uint16 782 | } 783 | 784 | // =======ZDO======= 785 | 786 | type ZdoNwkAddrReq struct { 787 | IEEEAddress string `hex:"8"` 788 | ReqType ReqType 789 | StartIndex uint8 790 | } 791 | 792 | type ZdoIeeeAddrReq struct { 793 | ShortAddr string `hex:"2"` 794 | ReqType ReqType 795 | StartIndex uint8 796 | } 797 | 798 | type ZdoNodeDescReq struct { 799 | DstAddr string `hex:"2"` 800 | NWKAddrOfInterest string `hex:"2"` 801 | } 802 | 803 | type ZdoPowerDescReq struct { 804 | DstAddr string `hex:"2"` 805 | NWKAddrOfInterest string `hex:"2"` 806 | } 807 | 808 | type ZdoUserDescReq struct { 809 | DstAddr string `hex:"2"` 810 | NWKAddrOfInterest string `hex:"2"` 811 | } 812 | 813 | type ZdoComplexDescReq struct { 814 | DstAddr string `hex:"2"` 815 | NWKAddrOfInterest string `hex:"2"` 816 | } 817 | 818 | type ZdoMatchDescReq struct { 819 | DstAddr string `hex:"2"` 820 | NWKAddrOfInterest string `hex:"2"` 821 | ProfileID uint16 822 | InClusterList []uint16 `size:"1"` 823 | OutClusterList []uint16 `size:"1"` 824 | } 825 | 826 | type ZdoSimpleDescReq struct { 827 | DstAddr string `hex:"2"` 828 | NWKAddrOfInterest string `hex:"2"` 829 | Endpoint uint8 830 | } 831 | 832 | type ZdoActiveEpReq struct { 833 | DstAddr string `hex:"2"` 834 | NWKAddrOfInterest string `hex:"2"` 835 | } 836 | 837 | type CapInfo struct { 838 | AlternatePANCoordinator uint8 `bits:"0b00000001" bitmask:"start"` 839 | Router uint8 `bits:"0b00000010"` 840 | MainPowered uint8 `bits:"0b00000100"` 841 | ReceiverOnWhenIdle uint8 `bits:"0b00001000"` 842 | Reserved1 uint8 `bits:"0b00010000"` 843 | Reserved2 uint8 `bits:"0b00100000"` 844 | Security uint8 `bits:"0b01000000"` 845 | AllocAddr uint8 `bits:"0b10000000" bitmask:"end"` 846 | } 847 | 848 | type ZdoEndDeviceAnnce struct { 849 | NwkAddr string `hex:"2"` 850 | IEEEAddr string `hex:"8"` 851 | Capabilities *CapInfo 852 | } 853 | 854 | type ZdoUserDescSet struct { 855 | DstAddr string `hex:"2"` 856 | NWKAddrOfInterest string `hex:"2"` 857 | UserDescriptor string `size:"1"` 858 | } 859 | 860 | type ServerMask struct { 861 | PrimTrustCenter uint16 `bits:"0x01" bitmask:"start"` 862 | BkupTrustCenter uint16 `bits:"0x02"` 863 | PrimBindTable uint16 `bits:"0x04"` 864 | BkupBindTable uint16 `bits:"0x08"` 865 | PrimDiscTable uint16 `bits:"0x10"` 866 | BkupDiscTable uint16 `bits:"0x20"` 867 | NetworkManager uint16 `bits:"0x40" bitmask:"end"` 868 | } 869 | 870 | type ZdoServerDiscReq struct { 871 | ServerMask *ServerMask 872 | } 873 | 874 | type ZdoEndDeviceBindReq struct { 875 | DstAddr string `hex:"2"` 876 | LocalCoordinatorAddr string `hex:"2"` 877 | IEEEAddr string `hex:"8"` 878 | Endpoint uint8 879 | ProfileID uint16 880 | InClusterList []uint16 `size:"1"` 881 | OutClusterList []uint16 `size:"1"` 882 | } 883 | 884 | type ZdoBindUnbindReq struct { 885 | DstAddr string `hex:"2"` 886 | SrcAddress string `hex:"8"` 887 | SrcEndpoint uint8 888 | ClusterID uint16 889 | DstAddrMode AddrMode 890 | DstAddress string `hex:"8"` 891 | DstEndpoint uint8 892 | } 893 | 894 | type Channels struct { 895 | Channel11 uint32 `bits:"0x00000800" bitmask:"start"` 896 | Channel12 uint32 `bits:"0x00001000"` 897 | Channel13 uint32 `bits:"0x00002000"` 898 | Channel14 uint32 `bits:"0x00004000"` 899 | Channel15 uint32 `bits:"0x00008000"` 900 | Channel16 uint32 `bits:"0x00010000"` 901 | Channel17 uint32 `bits:"0x00020000"` 902 | Channel18 uint32 `bits:"0x00040000"` 903 | Channel19 uint32 `bits:"0x00080000"` 904 | Channel20 uint32 `bits:"0x00100000"` 905 | Channel21 uint32 `bits:"0x00200000"` 906 | Channel22 uint32 `bits:"0x00400000"` 907 | Channel23 uint32 `bits:"0x00800000"` 908 | Channel24 uint32 `bits:"0x01000000"` 909 | Channel25 uint32 `bits:"0x02000000"` 910 | Channel26 uint32 `bits:"0b04000000" bitmask:"end"` 911 | } 912 | 913 | type ZdoMgmtNwkDiskReq struct { 914 | DstAddr string `hex:"2"` 915 | ScanChannels *Channels 916 | ScanDuration uint8 917 | StartIndex uint8 918 | } 919 | 920 | type ZdoMgmtLqiReq struct { 921 | DstAddr string `hex:"2"` 922 | StartIndex uint8 923 | } 924 | 925 | type ZdoMgmtRtgReq struct { 926 | DstAddr string `hex:"2"` 927 | StartIndex uint8 928 | } 929 | 930 | type ZdoMgmtBindReq struct { 931 | DstAddr string `hex:"2"` 932 | StartIndex uint8 933 | } 934 | 935 | type RemoveChildrenRejoin struct { 936 | Rejoin uint8 `bits:"0b00000001" bitmask:"start"` 937 | RemoveChildren uint8 `bits:"0b00000010" bitmask:"end"` 938 | } 939 | 940 | type ZdoMgmtLeaveReq struct { 941 | DstAddr string `hex:"2"` 942 | DeviceAddr string `hex:"8"` 943 | RemoveChildrenRejoin *RemoveChildrenRejoin 944 | } 945 | 946 | type ZdoMgmtDirectJoinReq struct { 947 | DstAddr string `hex:"2"` 948 | DeviceAddr string `hex:"8"` 949 | CapInfo *CapInfo 950 | } 951 | 952 | type ZdoMgmtPermitJoinReq struct { 953 | AddrMode AddrMode 954 | DstAddr string `hex:"2"` 955 | Duration uint8 956 | TCSignificance uint8 957 | } 958 | 959 | type ZdoMgmtNwkUpdateReq struct { 960 | DstAddr string `hex:"2"` 961 | DstAddrMode AddrMode 962 | ChannelMask *Channels 963 | ScanDuration uint8 964 | } 965 | 966 | type ZdoMsgCbRegister struct { 967 | ClusterID uint16 968 | } 969 | 970 | type ZdoMsgCbRemove struct { 971 | ClusterID uint16 972 | } 973 | 974 | type ZdoStartupFromApp struct { 975 | StartDelay uint16 976 | } 977 | 978 | type ZdoStartupFromAppResponse struct { 979 | Status StartupFromAppStatus 980 | } 981 | 982 | type ZdoSetLinkKey struct { 983 | ShortAddr string `hex:"2"` 984 | IEEEAddr string `hex:"8"` 985 | LinkKeyData [16]uint8 986 | } 987 | 988 | type ZdoRemoveLinkKey struct { 989 | IEEEAddr string `hex:"8"` 990 | } 991 | 992 | type ZdoGetLinkKey struct { 993 | IEEEAddr string `hex:"8"` 994 | } 995 | 996 | type ZdoGetLinkKeyResponse struct { 997 | Status Status 998 | IEEEAddr string `hex:"8"` 999 | LinkKeyData [16]uint8 1000 | } 1001 | 1002 | type ZdoNwkDiscoveryReq struct { 1003 | ScanChannels *Channels 1004 | ScanDuration uint8 1005 | } 1006 | 1007 | type ZdoJoinReq struct { 1008 | LogicalChannel uint8 1009 | PanID uint16 1010 | ExtendedPanID uint64 //64-bit extended PAN ID (ver. 1.1 only). If not v1.1 or don't care, use all 0xFF 1011 | ChosenParent string `hex:"2"` 1012 | ParentDepth uint8 1013 | StackProfile uint8 1014 | } 1015 | 1016 | type ZdoSetRejoinParameters struct { 1017 | BackoffDuration uint32 1018 | ScanDuration uint32 1019 | } 1020 | 1021 | type ZdoSecAddLinkKey struct { 1022 | ShortAddress string `hex:"2"` 1023 | ExtendedAddress string `hex:"8"` 1024 | Key [16]uint8 1025 | } 1026 | 1027 | type ZdoSecEntryLookupExt struct { 1028 | ExtendedAddress string `hex:"8"` 1029 | Entry [5]uint8 1030 | } 1031 | 1032 | type ZdoSecEntryLookupExtResponse struct { 1033 | AMI uint16 1034 | KeyNVID uint16 1035 | AuthenticationOption uint8 1036 | } 1037 | 1038 | type ZdoSecDeviceRemove struct { 1039 | ExtendedAddress string `hex:"8"` 1040 | } 1041 | 1042 | type ZdoExtRouteDisc struct { 1043 | DestinationAddress string `hex:"2"` 1044 | Options uint8 1045 | Radius uint8 1046 | } 1047 | 1048 | type ZdoExtRouteCheck struct { 1049 | DestinationAddress string `hex:"2"` 1050 | RTStatus uint8 1051 | Options uint8 1052 | } 1053 | 1054 | type ZdoExtRemoveGroup struct { 1055 | Endpoint uint8 1056 | GroupID uint16 1057 | } 1058 | 1059 | type ZdoExtRemoveAllGroup struct { 1060 | Endpoint uint8 1061 | } 1062 | 1063 | type ZdoExtFindAllGroupsEndpoint struct { 1064 | Endpoint uint8 1065 | GroupList []uint16 `size:"1"` 1066 | } 1067 | 1068 | type ZdoExtFindAllGroupsEndpointResponse struct { 1069 | Groups []uint16 `size:"1"` 1070 | } 1071 | 1072 | type ZdoExtFindGroup struct { 1073 | Endpoint uint8 1074 | GroupID uint16 1075 | } 1076 | 1077 | type ZdoExtFindGroupResponse struct { 1078 | Status Status 1079 | GroupID uint16 1080 | Name string `size:"1"` 1081 | } 1082 | 1083 | type ZdoExtAddGroup struct { 1084 | Endpoint uint8 1085 | GroupID uint16 1086 | GroupName string `size:"1"` 1087 | } 1088 | 1089 | type ZdoExtCountAllGroupsResponse struct { 1090 | Count uint8 1091 | } 1092 | 1093 | type ZdoExtRxIdle struct { 1094 | SetFlag uint8 1095 | SetValue uint8 1096 | } 1097 | 1098 | type ZdoExtUpdateNwkKey struct { 1099 | DestinationAddress string `hex:"2"` 1100 | KeySeqNum uint8 1101 | Key [128]uint8 1102 | } 1103 | 1104 | type ZdoExtSwitchNwkKey struct { 1105 | DestinationAddress string `hex:"2"` 1106 | KeySeqNum uint8 1107 | } 1108 | 1109 | type ZdoExtNwkInfoResponse struct { 1110 | ShortAddress string `hex:"2"` 1111 | PanID uint16 1112 | ParentAddress string `hex:"2"` 1113 | ExtendedPanID uint64 1114 | ExtendedParentAddress string `hex:"8"` 1115 | Channel uint16 //uint16 or uint8????? 1116 | } 1117 | 1118 | type ZdoExtSeqApsRemoveReq struct { 1119 | NwkAddress string `hex:"2"` 1120 | ExtendedAddress string `hex:"8"` 1121 | ParentAddress string `hex:"2"` 1122 | } 1123 | 1124 | type ZdoExtSetParams struct { 1125 | UseMulticast uint8 1126 | } 1127 | 1128 | type ZdoNwkAddrOfInterestReq struct { 1129 | DestAddr string `hex:"2"` 1130 | NwkAddrOfInterest string `hex:"2"` 1131 | Cmd uint8 1132 | } 1133 | 1134 | type ZdoNwkAddrRsp struct { 1135 | Status Status 1136 | IEEEAddr string `hex:"8"` 1137 | NwkAddr string `hex:"2"` 1138 | StartIndex uint8 1139 | AssocDevList []string `size:"1" hex:"2"` 1140 | } 1141 | 1142 | type ZdoIEEEAddrRsp struct { 1143 | Status Status 1144 | IEEEAddr string `hex:"8"` 1145 | NwkAddr string `hex:"2"` 1146 | StartIndex uint8 1147 | AssocDevList []string `size:"1" hex:"2"` 1148 | } 1149 | 1150 | type ZdoNodeDescRsp struct { 1151 | SrcAddr string `hex:"2"` 1152 | Status Status 1153 | NWKAddrOfInterest string `hex:"2"` 1154 | LogicalType LogicalType `bits:"0b00000011" bitmask:"start"` 1155 | ComplexDescriptorAvailable uint8 `bits:"0b00001000"` 1156 | UserDescriptorAvailable uint8 `bits:"0b00010000" bitmask:"end"` 1157 | APSFlags uint8 `bits:"0b00011111" bitmask:"start"` 1158 | FrequencyBand uint8 `bits:"0b11100000" bitmask:"end"` 1159 | MacCapabilitiesFlags *CapInfo 1160 | ManufacturerCode uint16 1161 | MaxBufferSize uint8 1162 | MaxInTransferSize uint16 1163 | ServerMask *ServerMask 1164 | MaxOutTransferSize uint16 1165 | DescriptorCapabilities uint8 1166 | } 1167 | 1168 | type ZdoPowerDescRsp struct { 1169 | SrcAddr string `hex:"2"` 1170 | Status Status 1171 | NWKAddr string `hex:"2"` 1172 | CurrentPowerMode uint8 `bits:"0b00001111" bitmask:"start"` 1173 | AvailablePowerSources uint8 `bits:"0b11110000" bitmask:"end"` 1174 | CurrentPowerSource uint8 `bits:"0b00001111" bitmask:"start"` 1175 | CurrentPowerSourceLevel uint8 `bits:"0b11110000" bitmask:"end"` 1176 | } 1177 | 1178 | type ZdoSimpleDescRsp struct { 1179 | SrcAddr string `hex:"2"` 1180 | Status Status 1181 | NWKAddr string `hex:"2"` 1182 | Len uint8 1183 | Endpoint uint8 1184 | ProfileID uint16 1185 | DeviceID uint16 1186 | DeviceVersion uint8 1187 | InClusterList []uint16 `size:"1"` 1188 | OutClusterList []uint16 `size:"1"` 1189 | } 1190 | 1191 | type ZdoActiveEpRsp struct { 1192 | SrcAddr string `hex:"2"` 1193 | Status Status 1194 | NWKAddr string `hex:"2"` 1195 | ActiveEPList []uint8 `size:"1"` 1196 | } 1197 | 1198 | type ZdoMatchDescRsp struct { 1199 | SrcAddr string `hex:"2"` 1200 | Status Status 1201 | NWKAddr string `hex:"2"` 1202 | MatchList []uint8 `size:"1"` 1203 | } 1204 | 1205 | type ZdoComplexDescRsp struct { 1206 | SrcAddr string `hex:"2"` 1207 | Status Status 1208 | NWKAddr string `hex:"2"` 1209 | ComplexDescriptor string `size:"1"` 1210 | } 1211 | 1212 | type ZdoUserDescRsp struct { 1213 | SrcAddr string `hex:"2"` 1214 | Status Status 1215 | NWKAddr string `hex:"2"` 1216 | UserDescriptor string `size:"1"` 1217 | } 1218 | 1219 | type ZdoUserDescConf struct { 1220 | SrcAddr string `hex:"2"` 1221 | Status Status 1222 | NWKAddr string `hex:"2"` 1223 | } 1224 | 1225 | type ZdoServerDiscRsp struct { 1226 | SrcAddr string `hex:"2"` 1227 | Status Status 1228 | ServerMask *ServerMask 1229 | } 1230 | 1231 | type ZdoEndDeviceBindRsp struct { 1232 | SrcAddr string `hex:"2"` 1233 | Status Status 1234 | } 1235 | 1236 | type ZdoBindRsp struct { 1237 | SrcAddr string `hex:"2"` 1238 | Status Status 1239 | } 1240 | 1241 | type ZdoUnbindRsp struct { 1242 | SrcAddr string `hex:"2"` 1243 | Status Status 1244 | } 1245 | 1246 | type Network struct { 1247 | PanID uint16 `bound:"8"` 1248 | LogicalChannel uint8 1249 | StackProfile uint8 `bits:"0b00001111" bitmask:"start"` 1250 | ZigbeeVersion uint8 `bits:"0b11110000" bitmask:"end"` 1251 | BeaconOrder uint8 `bits:"0b00001111" bitmask:"start"` 1252 | SuperFrameOrder uint8 `bits:"0b11110000" bitmask:"end"` 1253 | PermitJoin uint8 1254 | } 1255 | 1256 | type ZdoMgmtNwkDiscRsp struct { 1257 | SrcAddr string `hex:"2"` 1258 | Status Status 1259 | NetworkCount uint8 1260 | StartIndex uint8 1261 | NetworkList []*Network `size:"1"` 1262 | } 1263 | 1264 | type NeighborLqi struct { 1265 | ExtendedPanID uint64 1266 | ExtendedAddress string `hex:"8"` 1267 | NetworkAddress string `hex:"2"` 1268 | DeviceType LqiDeviceType `bits:"0b00000011" bitmask:"start"` 1269 | RxOnWhenIdle uint8 `bits:"0b00001100"` 1270 | Relationship uint8 `bits:"0b00110000" bitmask:"end"` 1271 | PermitJoining uint8 1272 | Depth uint8 1273 | LQI uint8 1274 | } 1275 | 1276 | type ZdoMgmtLqiRsp struct { 1277 | SrcAddr string `hex:"2"` 1278 | Status Status 1279 | NeighborTableEntries uint8 1280 | StartIndex uint8 1281 | NeighborLqiList []*NeighborLqi `size:"1"` 1282 | } 1283 | 1284 | type Route struct { 1285 | DestinationAddress string `hex:"2"` 1286 | Status RouteStatus 1287 | NextHop string `hex:"2"` 1288 | } 1289 | 1290 | type ZdoMgmtRtgRsp struct { 1291 | SrcAddr string `hex:"2"` 1292 | Status Status 1293 | RoutingTableEntries uint8 1294 | StartIndex uint8 1295 | RoutingTable []*Route `size:"1"` 1296 | } 1297 | 1298 | type Addr struct { 1299 | AddrMode AddrMode 1300 | ShortAddr string `hex:"2" cond:"uint:AddrMode!=3"` 1301 | ExtendedAddr string `hex:"8" cond:"uint:AddrMode==3"` 1302 | DstEndpoint uint8 `cond:"uint:AddrMode==3"` 1303 | } 1304 | 1305 | type Binding struct { 1306 | SrcAddr string `hex:"8"` 1307 | SrcEndpoint uint8 1308 | ClusterID uint16 1309 | DstAddr *Addr 1310 | } 1311 | 1312 | type ZdoMgmtBindRsp struct { 1313 | SrcAddr string `hex:"2"` 1314 | Status Status 1315 | BindTableEntries uint8 1316 | StartIndex uint8 1317 | BindTable []*Binding `size:"1"` 1318 | } 1319 | 1320 | type ZdoMgmtLeaveRsp struct { 1321 | SrcAddr string `hex:"2"` 1322 | Status Status 1323 | } 1324 | 1325 | type ZdoMgmtDirectJoinRsp struct { 1326 | SrcAddr string `hex:"2"` 1327 | Status Status 1328 | } 1329 | 1330 | type ZdoMgmtPermitJoinRsp struct { 1331 | SrcAddr string `hex:"2"` 1332 | Status Status 1333 | } 1334 | 1335 | type ZdoStateChangeInd struct { 1336 | State DeviceState 1337 | } 1338 | 1339 | type ZdoEndDeviceAnnceInd struct { 1340 | SrcAddr string `hex:"2"` 1341 | NwkAddr string `hex:"2"` 1342 | IEEEAddr string `hex:"8"` 1343 | Capabilities *CapInfo 1344 | } 1345 | 1346 | type ZdoMatchDescRpsSent struct { 1347 | NwkAddr string `hex:"2"` 1348 | InClusterList []uint16 `size:"1"` 1349 | OutClusterList []uint16 `size:"1"` 1350 | } 1351 | 1352 | type ZdoStatusErrorRsp struct { 1353 | SrcAddr string `hex:"2"` 1354 | Status Status 1355 | } 1356 | 1357 | type ZdoSrcRtgInd struct { 1358 | DstAddr string `hex:"2"` 1359 | RelayList []string `size:"1" hex:"2"` 1360 | } 1361 | 1362 | type Beacon struct { 1363 | SrcAddr string `hex:"2"` 1364 | PanID uint16 1365 | LogicalChannel uint8 1366 | PermitJoining uint8 1367 | RouterCapacity uint8 1368 | DeviceCapacity uint8 1369 | ProtocolVersion uint8 1370 | StackProfile uint8 1371 | LQI uint8 1372 | Depth uint8 1373 | UpdateID uint8 1374 | ExtendedPanID uint64 1375 | } 1376 | 1377 | type ZdoBeaconNotifyInd struct { 1378 | BeaconList []*Beacon `size:"1"` 1379 | } 1380 | 1381 | type ZdoJoinCnf struct { 1382 | Status Status 1383 | DeviceAddress string `hex:"2"` 1384 | ParentAddress string `hex:"2"` 1385 | } 1386 | 1387 | type ZdoNwkDiscoveryCnf struct { 1388 | Status Status 1389 | } 1390 | 1391 | type ZdoLeaveInd struct { 1392 | SrcAddr string `hex:"2"` 1393 | ExtAddr string `hex:"8"` 1394 | Request uint8 1395 | Remove uint8 1396 | Rejoin uint8 1397 | } 1398 | 1399 | type ZdoMsgCbIncoming struct { 1400 | SrcAddr string `hex:"2"` 1401 | WasBroadcast uint8 1402 | ClusterID uint16 1403 | SecurityUse uint8 1404 | SeqNum uint8 1405 | MacDstAddr string `hex:"2"` 1406 | Data []uint8 1407 | } 1408 | 1409 | type ZdoTcDevInd struct { 1410 | SrcNwkAddr string `hex:"2"` 1411 | SrcIEEEAddr string `hex:"8"` 1412 | ParentNwkAddr string `hex:"2"` 1413 | } 1414 | 1415 | type ZdoPermitJoinInd struct { 1416 | PermitJoinDuration uint8 1417 | } 1418 | 1419 | // =======APP_CNF======= 1420 | 1421 | type AppCnfSetNwkFrameCounter struct { 1422 | FrameCounterValue uint8 1423 | } 1424 | 1425 | type AppCnfSetDefaultEndDeviceTimeout struct { 1426 | Timeout Timeout 1427 | } 1428 | 1429 | type AppCnfSetEndDeviceTimeout struct { 1430 | Timeout Timeout 1431 | } 1432 | 1433 | type AppCnfSetAllowRejoinTcPolicy struct { 1434 | AllowRejoin uint8 1435 | } 1436 | 1437 | type AppCnfBdbStartCommissioning struct { 1438 | CommissioningMode CommissioningMode 1439 | } 1440 | 1441 | type AppCnfBdbSetChannel struct { 1442 | IsPrimary uint8 1443 | Channel *Channels 1444 | } 1445 | 1446 | type AppCnfBdbAddInstallCode struct { 1447 | InstallCodeFormat InstallCodeFormat 1448 | IEEEAddr string `hex:"8"` 1449 | InstallCode []uint8 1450 | } 1451 | 1452 | type AppCnfBdbSetTcRequireKeyExchange struct { 1453 | BdbTrustCenterRequireKeyExchange uint8 1454 | } 1455 | 1456 | type AppCnfBdbSetJoinUsesInstallCodeKey struct { 1457 | BdbJoinUsesInstallCodeKey uint8 1458 | } 1459 | 1460 | type AppCnfBdbSetActiveDefaultCentralizedKey struct { 1461 | UseGlobal uint8 1462 | InstallCode [18]uint8 1463 | } 1464 | 1465 | type RemainingCommissioningModes struct { 1466 | InitiatorTl uint8 `bits:"0x01" bitmask:"start"` 1467 | NwkSteering uint8 `bits:"0x02"` 1468 | NwkFormation uint8 `bits:"0x04"` 1469 | FindingBinding uint8 `bits:"0x08"` 1470 | Initialization uint8 `bits:"0x10"` 1471 | ParentLost uint8 `bits:"0x20" bitmask:"end"` 1472 | } 1473 | 1474 | type AppCnfBdbCommissioningNotification struct { 1475 | CommissioningStatus CommissioningStatus 1476 | CommissioningMode CommissioningMode 1477 | RemainingCommissioningModes *RemainingCommissioningModes 1478 | } 1479 | 1480 | // =======GP======= 1481 | 1482 | type TxOptions struct { 1483 | UseGpTxQueue uint8 `bits:"0b00000001" bitmask:"start"` 1484 | UseCSMAorCA uint8 `bits:"0b00000010"` 1485 | UseMacAck uint8 `bits:"0b00000100"` 1486 | GPDFFrameTypeForTx uint8 `bits:"0b00011000"` 1487 | TxOnMatchingEndpoint uint8 `bits:"0b00100000" bitmask:"end"` 1488 | } 1489 | 1490 | type GpDataReq struct { 1491 | Action GpAction 1492 | TxOptions *TxOptions 1493 | ApplicationID uint8 1494 | SrcID uint32 1495 | GPDIEEEAddress string `hex:"8"` 1496 | Endpoint uint8 1497 | GPDCommandID uint8 1498 | GPDASDU []uint8 `size:"1"` 1499 | GPEPHandle uint8 1500 | GPTxQueueEntryLifetime uint32 `bound:"3"` 1501 | } 1502 | 1503 | type GpSecRsp struct { 1504 | Status GpStatus 1505 | DGPStubHandle uint8 1506 | ApplicationID uint8 1507 | SrcID uint32 1508 | GPDIEEEAddress string `hex:"8"` 1509 | Endpoint uint8 1510 | GPDFSecurityLevel uint8 1511 | GPDFKeyType uint8 1512 | GPDKey [16]uint8 1513 | GPDSecurityFrameCounter uint32 1514 | } 1515 | 1516 | type GpDataCnf struct { 1517 | Status Status 1518 | GPMPDUHandle uint8 1519 | } 1520 | 1521 | type GpSecReq struct { 1522 | ApplicationID uint8 1523 | SrcID uint32 1524 | GPDIEEEAddress string `hex:"8"` 1525 | Endpoint uint8 1526 | GPDFSecurityLevel uint8 1527 | GPDFKeyType uint8 1528 | GPDSecurityFrameCounter uint32 1529 | DGPStubHandle uint8 1530 | } 1531 | 1532 | type GpDataInd struct { 1533 | Status GpDataIndStatus 1534 | RSSI uint8 1535 | LinkQuality uint8 1536 | SeqNumber uint8 1537 | SrcAddrMode AddrMode 1538 | SrcPANId uint16 1539 | SrcAddress string `hex:"8"` 1540 | DstAddrMode AddrMode 1541 | DstPANId uint16 1542 | DstAddress string `hex:"8"` 1543 | GPMPDU []uint8 `size:"1"` 1544 | } 1545 | -------------------------------------------------------------------------------- /processor.go: -------------------------------------------------------------------------------- 1 | package znp 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/dyrkin/unp-go" 9 | 10 | "github.com/dyrkin/bin" 11 | "github.com/dyrkin/znp-go/reflection" 12 | "github.com/dyrkin/znp-go/request" 13 | ) 14 | 15 | func (znp *Znp) Start() { 16 | startProcessors(znp) 17 | startIncomingFrameLoop(znp) 18 | znp.started = true 19 | } 20 | 21 | func (znp *Znp) Stop() { 22 | znp.started = false 23 | } 24 | 25 | func (znp *Znp) ProcessRequest(commandType unp.CommandType, subsystem unp.Subsystem, command byte, req interface{}, resp interface{}) error { 26 | frame := &unp.Frame{ 27 | CommandType: commandType, 28 | Subsystem: subsystem, 29 | Command: command, 30 | Payload: bin.Encode(req), 31 | } 32 | return processFrame(znp, frame, resp) 33 | } 34 | 35 | func processFrame(znp *Znp, frame *unp.Frame, resp interface{}) (err error) { 36 | if !znp.started { 37 | panic("Znp is not started. Call znp.Start() before") 38 | } 39 | completed := make(chan bool, 1) 40 | go func() { 41 | switch frame.CommandType { 42 | case unp.C_SREQ: 43 | outgoing := request.NewSync(frame) 44 | znp.outbound <- outgoing 45 | select { 46 | case frame := <-outgoing.SyncRsp(): 47 | bin.Decode(frame.Payload, resp) 48 | case err = <-outgoing.SyncErr(): 49 | } 50 | case unp.C_AREQ: 51 | outgoing := request.NewAsync(frame) 52 | znp.outbound <- outgoing 53 | default: 54 | err = fmt.Errorf("unsupported command type: %s ", frame.CommandType) 55 | } 56 | completed <- true 57 | }() 58 | <-completed 59 | return 60 | } 61 | 62 | func startProcessors(znp *Znp) { 63 | syncRsp := make(chan *unp.Frame) 64 | syncErr := make(chan error) 65 | syncRequestProcessor := makeSyncRequestProcessor(znp, syncRsp, syncErr) 66 | asyncRequestProcessor := makeAsyncRequestProcessor(znp) 67 | syncResponseProcessor := makeSyncResponseProcessor(syncRsp, syncErr) 68 | asyncResponseProcessor := makeAsyncResponseProcessor(znp) 69 | outgoingProcessor := func() { 70 | for znp.started { 71 | select { 72 | case outgoing := <-znp.outbound: 73 | switch req := outgoing.(type) { 74 | case *request.Sync: 75 | syncRequestProcessor(req) 76 | case *request.Async: 77 | asyncRequestProcessor(req) 78 | } 79 | } 80 | } 81 | } 82 | incomingProcessor := func() { 83 | for znp.started { 84 | select { 85 | case frame := <-znp.inbound: 86 | switch frame.CommandType { 87 | case unp.C_SRSP: 88 | syncResponseProcessor(frame) 89 | case unp.C_AREQ: 90 | asyncResponseProcessor(frame) 91 | default: 92 | select { 93 | case znp.errors <- fmt.Errorf("unsupported frame received type: %v ", frame): 94 | default: 95 | } 96 | } 97 | } 98 | } 99 | } 100 | go incomingProcessor() 101 | go outgoingProcessor() 102 | } 103 | 104 | func startIncomingFrameLoop(znp *Znp) { 105 | incomingLoop := func() { 106 | for znp.started { 107 | frame, err := znp.u.ReadFrame() 108 | if err != nil { 109 | select { 110 | case znp.errors <- err: 111 | default: 112 | } 113 | } else { 114 | logFrame(frame, znp.inFramesLog) 115 | znp.inbound <- frame 116 | } 117 | } 118 | } 119 | go incomingLoop() 120 | } 121 | 122 | func makeSyncRequestProcessor(znp *Znp, syncRsp chan *unp.Frame, syncErr chan error) func(req *request.Sync) { 123 | return func(req *request.Sync) { 124 | frame := req.Frame() 125 | deadline := time.NewTimer(5 * time.Second) 126 | logFrame(frame, znp.outFramesLog) 127 | err := znp.u.WriteFrame(frame) 128 | if err != nil { 129 | req.SyncErr() <- err 130 | return 131 | } 132 | select { 133 | case _ = <-deadline.C: 134 | if !deadline.Stop() { 135 | req.SyncErr() <- fmt.Errorf("timed out while waiting response for command: 0x%x sent to subsystem: %s ", frame.Command, frame.Subsystem) 136 | } 137 | case response := <-syncRsp: 138 | deadline.Stop() 139 | req.SyncRsp() <- response 140 | case err := <-syncErr: 141 | deadline.Stop() 142 | req.SyncErr() <- err 143 | } 144 | } 145 | } 146 | 147 | func makeAsyncRequestProcessor(znp *Znp) func(req *request.Async) { 148 | return func(req *request.Async) { 149 | logFrame(req.Frame(), znp.outFramesLog) 150 | znp.u.WriteFrame(req.Frame()) 151 | } 152 | } 153 | 154 | var errorMessages = map[uint8]string{ 155 | 1: "Invalid subsystem", 156 | 2: "Invalid command ID", 157 | 3: "Invalid parameter", 158 | 4: "Invalid length", 159 | } 160 | 161 | func makeSyncResponseProcessor(syncRsp chan *unp.Frame, syncErr chan error) func(frame *unp.Frame) { 162 | return func(frame *unp.Frame) { 163 | if frame.Subsystem == unp.S_RES0 && frame.Command == 0 { 164 | errorCode := frame.Payload[0] 165 | syncErr <- errors.New(errorMessages[errorCode]) 166 | } else { 167 | syncRsp <- frame 168 | } 169 | } 170 | } 171 | 172 | func makeAsyncResponseProcessor(znp *Znp) func(frame *unp.Frame) { 173 | return func(frame *unp.Frame) { 174 | key := key{frame.Subsystem, frame.Command} 175 | if value, ok := asyncCommandRegistry[key]; ok { 176 | cp := reflection.Copy(value) 177 | bin.Decode(frame.Payload, cp) 178 | select { 179 | case znp.asyncInbound <- cp: 180 | default: 181 | } 182 | } else { 183 | select { 184 | case znp.errors <- fmt.Errorf("unknown async command received: %v", frame): 185 | default: 186 | } 187 | } 188 | } 189 | } 190 | 191 | func logFrame(frame *unp.Frame, logger chan *unp.Frame) { 192 | go func() { 193 | select { 194 | case logger <- frame: 195 | default: 196 | } 197 | }() 198 | 199 | } 200 | -------------------------------------------------------------------------------- /reflection/reflection.go: -------------------------------------------------------------------------------- 1 | package reflection 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/dyrkin/znp-go/util" 7 | ) 8 | 9 | func Copy(n interface{}) interface{} { 10 | v := reflect.ValueOf(n) 11 | switch v.Kind() { 12 | case reflect.Struct: 13 | copy := reflect.New(v.Type()).Elem() 14 | return copy.Interface() 15 | case reflect.Ptr: 16 | e := v.Elem() 17 | copy := reflect.New(e.Type()) 18 | return copy.Interface() 19 | } 20 | util.Panicf("reflection.Copy: Unsupported value: %#v", n) 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /reflection/reflection_test.go: -------------------------------------------------------------------------------- 1 | package reflection 2 | 3 | import ( 4 | "testing" 5 | 6 | . "gopkg.in/check.v1" 7 | ) 8 | 9 | func Test(t *testing.T) { TestingT(t) } 10 | 11 | type MySuite struct{} 12 | 13 | var _ = Suite(&MySuite{}) 14 | 15 | type Struct struct { 16 | v1 uint8 17 | v2 string 18 | } 19 | 20 | func (s *MySuite) TestCopy(c *C) { 21 | copy1 := Copy(&Struct{1, "2"}) 22 | 23 | c.Assert(copy1, DeepEquals, &Struct{}) 24 | 25 | copy2 := Copy(Struct{1, "2"}) 26 | 27 | c.Assert(copy2, DeepEquals, Struct{}) 28 | } 29 | -------------------------------------------------------------------------------- /request/async.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import unp "github.com/dyrkin/unp-go" 4 | 5 | type Async struct { 6 | frame *unp.Frame 7 | } 8 | 9 | func NewAsync(frame *unp.Frame) *Async { 10 | return &Async{frame} 11 | } 12 | 13 | func (a *Async) Frame() *unp.Frame { 14 | return a.frame 15 | } 16 | -------------------------------------------------------------------------------- /request/request.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import unp "github.com/dyrkin/unp-go" 4 | 5 | type Outgoing interface { 6 | Frame() *unp.Frame 7 | } 8 | -------------------------------------------------------------------------------- /request/sync.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import unp "github.com/dyrkin/unp-go" 4 | 5 | type Sync struct { 6 | frame *unp.Frame 7 | syncRsp chan *unp.Frame 8 | syncErr chan error 9 | } 10 | 11 | func NewSync(frame *unp.Frame) *Sync { 12 | return &Sync{frame, make(chan *unp.Frame, 1), make(chan error, 1)} 13 | } 14 | 15 | func (s *Sync) Frame() *unp.Frame { 16 | return s.frame 17 | } 18 | 19 | func (s *Sync) SyncRsp() chan *unp.Frame { 20 | return s.syncRsp 21 | } 22 | 23 | func (s *Sync) SyncErr() chan error { 24 | return s.syncErr 25 | } 26 | -------------------------------------------------------------------------------- /util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func Panicf(format string, v ...interface{}) { 8 | panic(fmt.Sprintf(format, v...)) 9 | } 10 | -------------------------------------------------------------------------------- /znp.go: -------------------------------------------------------------------------------- 1 | package znp 2 | 3 | import ( 4 | "github.com/dyrkin/unp-go" 5 | 6 | "github.com/dyrkin/znp-go/request" 7 | ) 8 | 9 | type Znp struct { 10 | u *unp.Unp 11 | outbound chan request.Outgoing 12 | inbound chan *unp.Frame 13 | asyncInbound chan interface{} 14 | errors chan error 15 | inFramesLog chan *unp.Frame 16 | outFramesLog chan *unp.Frame 17 | started bool 18 | } 19 | 20 | func New(u *unp.Unp) *Znp { 21 | znp := &Znp{ 22 | u: u, 23 | outbound: make(chan request.Outgoing), 24 | inbound: make(chan *unp.Frame), 25 | asyncInbound: make(chan interface{}), 26 | errors: make(chan error, 100), 27 | inFramesLog: make(chan *unp.Frame, 100), 28 | outFramesLog: make(chan *unp.Frame, 100), 29 | } 30 | return znp 31 | } 32 | 33 | func (znp *Znp) Errors() chan error { 34 | return znp.errors 35 | } 36 | 37 | func (znp *Znp) AsyncInbound() chan interface{} { 38 | return znp.asyncInbound 39 | } 40 | 41 | func (znp *Znp) InFramesLog() chan *unp.Frame { 42 | return znp.inFramesLog 43 | } 44 | 45 | func (znp *Znp) OutFramesLog() chan *unp.Frame { 46 | return znp.outFramesLog 47 | } 48 | 49 | func (znp *Znp) IsStarted() bool { 50 | return znp.started 51 | } 52 | --------------------------------------------------------------------------------