ZWLib.pm 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. ##############################################
  2. # $Id: ZWLib.pm 17186 2018-08-20 20:10:55Z rudolfkoenig $
  3. package main;
  4. # Known controller function.
  5. # Note: Known != implemented, see %sets & %gets for the implemented ones.
  6. use vars qw(%zw_func_id);
  7. use vars qw(%zw_type6);
  8. %zw_func_id= (
  9. '02' => 'SERIAL_API_GET_INIT_DATA',
  10. '03' => 'SERIAL_API_APPL_NODE_INFORMATION',
  11. '04' => 'APPLICATION_COMMAND_HANDLER',
  12. '05' => 'ZW_GET_CONTROLLER_CAPABILITIES',
  13. '06' => 'SERIAL_API_SET_TIMEOUTS',
  14. '07' => 'SERIAL_API_GET_CAPABILITIES',
  15. '08' => 'SERIAL_API_SOFT_RESET',
  16. '0b' => 'SERIAL_API_SETUP',
  17. '10' => 'ZW_SET_R_F_RECEIVE_MODE',
  18. '11' => 'ZW_SET_SLEEP_MODE',
  19. '12' => 'ZW_SEND_NODE_INFORMATION',
  20. '13' => 'ZW_SEND_DATA',
  21. '14' => 'ZW_SEND_DATA_MULTI',
  22. '15' => 'ZW_GET_VERSION',
  23. '16' => 'ZW_SEND_DATA_ABORT',
  24. '17' => 'ZW_R_F_POWER_LEVEL_SET',
  25. '18' => 'ZW_SEND_DATA_META',
  26. '19' => 'ZW_SEND_DATA_GENERIC', # Appl. Guide
  27. '1a' => 'ZW_SEND_DATA_META_GENERIC', # Appl. Guide
  28. '1b' => 'ZW_SET_ROUTING_INFO', # Appl. Guide
  29. '1c' => 'ZW_GET_RANDOM', # ZW_GET_RANDOM_WORD # Appl. Guide
  30. '1d' => 'ZW_RANDOM', # Appl. Guide
  31. '1e' => 'ZW_RF_POWER_LEVEL_REDISCOVERY_SET', # Appl. Guide
  32. '20' => 'MEMORY_GET_ID',
  33. '21' => 'MEMORY_GET_BYTE',
  34. '22' => 'MEMORY_PUT_BYTE',
  35. '23' => 'MEMORY_GET_BUFFER',
  36. '24' => 'MEMORY_PUT_BUFFER',
  37. '27' => 'FLASH_AUTO_PROG_SET',
  38. '28' => 'ZW_NVR_GET_VALUE',
  39. '29' => 'NVM_GET_ID',
  40. '2a' => 'NVM_EXT_READ_LONG_BUFFER',
  41. '2b' => 'NVM_EXT_WRITE_LONG_BUFFER',
  42. '2c' => 'NVM_EXT_READ_LONG_BYTE',
  43. '2d' => 'NVM_EXT_WRITE_LONG_BYTE',
  44. '30' => 'CLOCK_SET',
  45. '31' => 'CLOCK_GET',
  46. '32' => 'CLOCK_COMPARE',
  47. '33' => 'RTC_TIMER_CREATE',
  48. '34' => 'RTC_TIMER_READ',
  49. '35' => 'RTC_TIMER_DELETE',
  50. '36' => 'RTC_TIMER_CALL',
  51. '37' => 'ZW_CLEAR_TX_TIMERS',
  52. '38' => 'ZW_GET_TX_TIMERS',
  53. '39' => 'CLEAR_NETWORK_STATS',
  54. '3a' => 'GET_NETWORK_STATS',
  55. '3b' => 'GET_BACKGROUND_RSSI',
  56. '3f' => 'REMOVE_NODEID_FROM_NETWORK',
  57. '40' => 'ZW_SET_LEARN_NODE_STATE',
  58. '41' => 'ZW_GET_NODE_PROTOCOL_INFO',
  59. '42' => 'ZW_SET_DEFAULT',
  60. '43' => 'ZW_NEW_CONTROLLER',
  61. '44' => 'ZW_REPLICATION_COMMAND_COMPLETE',
  62. '45' => 'ZW_REPLICATION_SEND_DATA',
  63. '46' => 'ZW_ASSIGN_RETURN_ROUTE',
  64. '47' => 'ZW_DELETE_RETURN_ROUTE',
  65. '48' => 'ZW_REQUEST_NODE_NEIGHBOR_UPDATE',
  66. '49' => 'ZW_APPLICATION_UPDATE',
  67. '4a' => 'ZW_ADD_NODE_TO_NETWORK',
  68. '4b' => 'ZW_REMOVE_NODE_FROM_NETWORK',
  69. '4c' => 'ZW_CREATE_NEW_PRIMARY',
  70. '4d' => 'ZW_CONTROLLER_CHANGE',
  71. '4f' => 'ZW_ASSIGN_PRIORITY_RETURN_ROUTE',
  72. '50' => 'ZW_SET_LEARN_MODE',
  73. '51' => 'ZW_ASSIGN_SUC_RETURN_ROUTE',
  74. '52' => 'ZW_ENABLE_SUC',
  75. '53' => 'ZW_REQUEST_NETWORK_UPDATE',
  76. '54' => 'ZW_SET_SUC_NODE_ID',
  77. '55' => 'ZW_DELETE_SUC_RETURN_ROUTE',
  78. '56' => 'ZW_GET_SUC_NODE_ID',
  79. '57' => 'ZW_SEND_SUC_ID',
  80. '58' => 'ZW_ASSIGN_PRIORITY_SUC_RETURN_ROUTE',
  81. '59' => 'ZW_REDISCOVERY_NEEDED',
  82. '5b' => 'ZW_SUPPORT_9600_ONLY', # Appl. Guide
  83. '5c' => 'ZW_REQUEST_NEW_ROUTE_DESTINATIONS', # Appl. Guide
  84. '5d' => 'ZW_IS_NODE_WIHTIN_DIRECT_RANGE', # Appl. Guide
  85. '5e' => 'ZW_EXPLORE_REQUEST_INCLUSION',
  86. '5f' => 'ZW_EXPLORE_REQUEST_EXCLUSION',
  87. '60' => 'ZW_REQUEST_NODE_INFO',
  88. '61' => 'ZW_REMOVE_FAILED_NODE_ID',
  89. '62' => 'ZW_IS_FAILED_NODE',
  90. '63' => 'ZW_REPLACE_FAILED_NODE',
  91. '70' => 'TIMER_START',
  92. '71' => 'TIMER_RESTART',
  93. '72' => 'TIMER_CANCEL',
  94. '73' => 'TIMER_CALL',
  95. '78' => 'ZW_FIRMWARE_UPDATE_NVM',
  96. '80' => 'GET_ROUTING_TABLE_LINE',
  97. '81' => 'GET_T_X_COUNTER',
  98. '82' => 'RESET_T_X_COUNTER',
  99. '83' => 'STORE_NODE_INFO',
  100. '84' => 'STORE_HOME_ID',
  101. '90' => 'LOCK_ROUTE_RESPONSE',
  102. '91' => 'ZW_SEND_DATA_ROUTE_DEMO',
  103. '92' => 'ZW_GET_PRIORITY_ROUTE',
  104. '93' => 'ZW_SET_PRIORITY_ROUTE',
  105. '95' => 'SERIAL_API_TEST',
  106. 'a0' => 'SERIAL_API_SLAVE_NODE_INFO',
  107. 'a1' => 'APPLICATION_SLAVE_COMMAND_HANDLER',
  108. 'a2' => 'ZW_SEND_SLAVE_NODE_INFO',
  109. 'a3' => 'ZW_SEND_SLAVE_DATA',
  110. 'a4' => 'ZW_SET_SLAVE_LEARN_MODE',
  111. 'a5' => 'ZW_GET_VIRTUAL_NODES',
  112. 'a6' => 'ZW_IS_VIRTUAL_NODE',
  113. 'a8' => 'ZW_APPLICATION_COMMAND_HANLDER_BRIDGE', # Appl. Guide
  114. 'a9' => 'ZW_SEND_DATA_BRIDGE', # Appl. Guide
  115. 'aa' => 'ZW_SEND_DATA_META_BRIDGE', # Appl. Guide
  116. 'ab' => 'ZW_SEND_DATA_MULTI_BRIDGE', # Appl. Guide
  117. 'b4' => 'ZW_SET_WUT_TIMEOUT', # Appl. Guide
  118. 'b6' => 'ZW_WATCHDOG_ENABLE',
  119. 'b7' => 'ZW_WATCHDOG_DISABLE',
  120. 'b8' => 'ZW_WATCHDOG_CHECK', # ZW_WATCHDOG_KICK # Appl. Guide
  121. 'b9' => 'ZW_SET_EXT_INT_LEVEL',
  122. 'ba' => 'ZW_RF_POWERLEVEL_GET',
  123. 'bb' => 'ZW_GET_NEIGHBOR_COUNT',
  124. 'bc' => 'ZW_ARE_NODES_NEIGHBOURS',
  125. 'bd' => 'ZW_TYPE_LIBRARY',
  126. 'be' => 'ZW_SEND_TEST_FRAME',
  127. 'bf' => 'ZW_GET_PROTOCOL_STATUS',
  128. 'd0' => 'ZW_SET_PROMISCUOUS_MODE',
  129. 'd1' => 'PROMISCUOUS_COMMAND_HANDLER',
  130. 'd2' => 'WATCHDOG_START',
  131. 'd3' => 'WATCHDOG_STOP',
  132. 'd4' => 'ZW_SET_ROUTING_MAX',
  133. 'f2' => 'ZME_FREQ_CHANGE',
  134. 'f4' => 'ZME_BOOTLOADER_FLASH',
  135. 'f5' => 'ZME_CAPABILITIES',
  136. );
  137. %zw_type6 = (
  138. '01' => 'GENERIC_CONTROLLER',
  139. '02' => 'STATIC_CONTROLLER',
  140. '03' => 'AV_CONTROL_POINT',
  141. '04' => 'DISPLAY',
  142. '05' => 'NETWORK_EXTENDER',
  143. '06' => 'APPLIANCE',
  144. '07' => 'SENSOR_NOTIFICATION',
  145. '08' => 'THERMOSTAT',
  146. '09' => 'WINDOW_COVERING',
  147. '0f' => 'REPEATER_SLAVE',
  148. '10' => 'SWITCH_BINARY',
  149. '11' => 'SWITCH_MULTILEVEL',
  150. '12' => 'SWITCH_REMOTE',
  151. '13' => 'SWITCH_TOGGLE',
  152. '15' => 'ZIP_NODE',
  153. '16' => 'VENTILATION',
  154. '17' => 'SECURITY_PANEL',
  155. '18' => 'WALL_CONTROLLER',
  156. '20' => 'SENSOR_BINARY',
  157. '21' => 'SENSOR_MULTILEVEL',
  158. '22' => 'WATER_CONTROL',
  159. '30' => 'METER_PULSE',
  160. '31' => 'METER',
  161. '40' => 'ENTRY_CONTROL',
  162. '50' => 'SEMI_INTEROPERABLE',
  163. 'a1' => 'SENSOR_ALARM',
  164. 'ff' => 'NON_INTEROPERABLE',
  165. );
  166. sub
  167. zwlib_parseNeighborList($$)
  168. {
  169. my ($iodev, $data) = @_;
  170. my $homeId = $iodev->{homeId};
  171. my $ioName = $iodev->{NAME};
  172. my @r = map { ord($_) } split("", pack('H*', $data));
  173. return "Bogus neighborList $data" if(int(@r) != 29);
  174. my @list;
  175. my $ioId = ReadingsVal($ioName, "homeId", "");
  176. $ioId = $1 if($ioId =~ m/CtrlNodeIdHex:(..)/);
  177. for my $byte (0..28) {
  178. my $bits = $r[$byte];
  179. for my $bit (0..7) {
  180. if($bits & (1<<$bit)) {
  181. my $dec = $byte*8+$bit+1;
  182. my $hex = sprintf("%02x", $dec);
  183. my $h = $modules{ZWave}{defptr}{"$homeId $hex"};
  184. push @list, ($hex eq $ioId ? $ioName :
  185. ($h ? $h->{NAME} : "UNKNOWN_$dec"));
  186. }
  187. }
  188. }
  189. return @list ? join(" ", @list) : "empty";
  190. }
  191. #####################################
  192. sub
  193. zwlib_checkSum_8($)
  194. {
  195. my ($data) = @_;
  196. my $cs = 0xff;
  197. map { $cs ^= ord($_) } split("", pack('H*', $data));
  198. return sprintf("%02x", $cs);
  199. }
  200. sub
  201. zwlib_checkSum_16($) # CRC16-CCITT (Polynom: 1021)
  202. {
  203. my ($data) = @_;
  204. my $crc = 0x1d0f;
  205. for my $c (split("", pack('H*', $data))) {
  206. my $x = ($crc>>8) ^ ord($c);
  207. $x ^= $x>>4;
  208. $crc = (($crc<<8) ^ ($x<<12) ^ ($x<<5) ^ $x) & 0xffff;
  209. }
  210. return sprintf("%04x", $crc);
  211. }
  212. sub
  213. zwlib_parseNodeInfo(@)
  214. {
  215. my @r = @_;
  216. my @list;
  217. my @type2 = qw(reserved0 2 SDK5.0x+4.2x SDK4.5x+6.0x reserved4
  218. reserved5 reserved6 reserved7);
  219. my @type2_1 = qw(reserved 9.6kbps 40kbps);
  220. my @type3 = qw(Security Controller SpecificDev RoutingSlave BeamCap
  221. FrequentListen250ms FrequentListen1000ms OptFunc);
  222. my @type4 = qw(reserved0 100kbps 200kbps);
  223. my @type4_1 = qw(N/A CentralStaticController SubStaticController
  224. PortableController PortableReportingController
  225. PortableSlave AlwaysOnSlave
  226. SleepingReportingSlave SleepingListeningSlave);
  227. my @type5 = qw(CONTROLLER STATIC_CONTROLLER SLAVE ROUTING_SLAVE);
  228. push @list, "ProtocolVers:" . $type2[($r[2]&0x7)];
  229. push @list, ($r[2] & 0x80) ? "listening" : "sleeping";
  230. push @list, "routing"
  231. if($r[2] & 0x40);
  232. push @list, "maxBaud:" . $type2_1[($r[2] & 0x38) >> 3]
  233. if($type2_1[($r[2] & 0x38) >> 3]);
  234. for my $bit (0..7) {
  235. push @list, $type3[$bit] if(($r[3] & (1<<$bit)) && $bit < @type3);
  236. }
  237. push @list, "SpeedExt:" . $type4[($r[4] & 0x7)]
  238. if($type4[($r[4] & 0x7)] !=0);
  239. push @list, "Reserved"
  240. if($r[4] &0x08);
  241. push @list, "RoleType:" . $type4_1[(($r[4] & 0x8) & 0xf0) >> 4]
  242. if($type4_1[(($r[4] & 0x8) & 0xf0) >> 4]);
  243. push @list, "BasicDevClass:" . $type5[$r[5]-1]
  244. if($r[5]>0 && $r[5] <= @type5);
  245. my $id = sprintf("%02x", $r[6]);
  246. push @list, "GenericDevClass:" . $zw_type6{$id}
  247. if($zw_type6{$id});
  248. push @list, "SpecificDevClass:" . sprintf("%02x", $r[7])
  249. if($r[7]);
  250. return join(" ", @list);
  251. }
  252. 1;