def set_channel_panid(self): # set radio channel t1 = tlvlib.create_set_tlv32(self.radio_instance, tlvlib.VARIABLE_RADIO_CHANNEL, self.radio_channel) # set radio PAN ID t2 = tlvlib.create_set_tlv32(self.radio_instance, tlvlib.VARIABLE_RADIO_PAN_ID, self.radio_panid) tlvlib.send_tlv([t1,t2], self.router_host)
def grab_device(self, target): # Do not try to grab targets that should not be grabbed if hasattr(target, 'next_update') and target.next_update < 0: return False IPv6Str = binascii.hexlify(socket.inet_pton(socket.AF_INET6, self.udp_address)) payloadStr = "000000020000%04x"%self.udp_port + IPv6Str + "%08x"%self.grab_location + "00000000" payload = binascii.unhexlify(payloadStr) self.log.info("[%s] Grabbing device => %s (%s)", target, payloadStr, str(len(payload))) t1 = tlvlib.create_set_tlv(0, tlvlib.VARIABLE_UNIT_CONTROLLER_ADDRESS, 3, payload) t2 = tlvlib.create_set_tlv32(0, tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG, self.watchdog_time) if hasattr(target, 'send_tlv'): if target.has_pending_tlv(t2): self.log.info("[%s] Already has pending grab request", target.address) return False if not target.send_tlv([t1,t2]): self.log.info("[%s] Failed to grab device (time out)", target.address) return False return True try: tlvlib.send_tlv([t1,t2], target) return True except socket.timeout: self.log.warning("[%s] Failed to grab device (time out)", str(target)) return False
def do_reboot(host, port, image=0): if image == 0: t = tlvlib.create_set_tlv32(0, tlvlib.VARIABLE_HARDWARE_RESET, 1) else: t = tlvlib.create_set_tlv32(0, tlvlib.VARIABLE_HARDWARE_RESET, tlvlib.HARDWARE_RESET_KEY | image) try: tlvlib.send_tlv(t, host, port, show_error=False, retry=False, timeout=0.2) except socket.timeout: # A timeout is expected since the node should reboot pass return True
def _process_get_response(self, tlv): if tlv.instance == 0: if tlv.variable == tlvlib.VARIABLE_UNIT_BOOT_TIMER: # Update the boot time estimation seconds, ns = tlvlib.convert_ieee64_time(tlv.int_value) last_boot_time = self.boot_time self.boot_time = self.last_seen - seconds # Assume reboot if the boot time backs at least 30 seconds if last_boot_time - self.boot_time > 30: self.log.info("REBOOT DETECTED!") elif tlv.variable == tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG: if self.next_update < 0: # Ignore watchdog in this device pass elif hasattr(tlv, 'int_value') and tlv.int_value > 0: self.log.debug("WDT updated! %d seconds remaining", tlv.int_value) self.next_update = self.last_seen + tlv.int_value - self._device_server.guard_time self.update_tries = 0 else: # Need to refresh watchdog t1 = tlvlib.create_set_tlv32( 0, tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG, self._device_server.watchdog_time) self.send_tlv(t1) elif tlv.variable == tlvlib.VARIABLE_SLEEP_DEFAULT_AWAKE_TIME: # This node is a sleepy node self.set_sleepy_device() elif self.button_instance and tlv.instance == self.button_instance: if tlv.variable == tlvlib.VARIABLE_GPIO_TRIGGER_COUNTER: self.button_counter = tlv.int_value elif tlv.variable == tlvlib.VARIABLE_EVENT_ARRAY and tlv.op == tlvlib.TLV_EVENT_RESPONSE: self.log.info("button pressed - %d times", self.button_counter) # Rearm the button self.arm_device(self.button_instance) de = DeviceEvent(self, EVENT_BUTTON, self.button_counter) self._device_server.send_event(de) elif self.motion_instance and tlv.instance == self.motion_instance: if tlv.variable == 0x100: self.motion_counter, = struct.unpack("!q", tlv.data[8:16]) elif tlv.variable == tlvlib.VARIABLE_EVENT_ARRAY and tlv.op == tlvlib.TLV_EVENT_RESPONSE: self.log.info("MOTION! - %d times", self.motion_counter) # Rearm the button self.arm_device(self.motion_instance) de = DeviceEvent(self, EVENT_MOTION, self.motion_counter) self._device_server.send_event(de) elif self.nstats_instance and tlv.instance == self.nstats_instance: if tlv.variable == tlvlib.VARIABLE_NSTATS_DATA: self._handle_nstats(tlv) elif self.temperature_instance and tlv.instance == self.temperature_instance: if tlv.variable == tlvlib.VARIABLE_TEMPERATURE: temperature = (tlv.int_value - 273150) / 1000.0 self.log.info("Temperature: " + str(round(temperature, 2)) + " C")
def do_erase(instance, host, port): # create Erase TLV t1 = tlvlib.create_set_tlv32(instance, tlvlib.VARIABLE_WRITE_CONTROL, tlvlib.FLASH_WRITE_CONTROL_ERASE) try: enc, tlvs = tlvlib.send_tlv(t1, host, port, 2.5) except socket.timeout: return False return tlvs[0].error == 0
def _wakeup_device(self, device, time): if device.is_sleepy_device() and device.sleep_instance is not None: print "requesting [" + device.address + "] to wakeup" t = tlvlib.create_set_tlv32(device.sleep_instance, tlvlib.VARIABLE_SLEEP_AWAKE_TIME_WHEN_NO_ACTIVITY, time * 1000L) device.send_tlv(t) else: print device.address,"is not a sleepy device"
def _manage_devices(self): while self.running: current_time = time.time() remove_list = [] for dev in self.get_devices(): # Check if there is need for discovery if not dev.is_discovered(): if dev.discovery_tries < 5: self.discover_device(dev) if not dev.is_discovered(): # Do a live check if needed... if dev.last_seen + 60 < current_time and dev.last_ping + 60 < current_time: self.ping(dev) # Remove non-discoverable devices after some time # so they can be tried again if dev.last_seen + 180 < current_time: print "Removing", dev.address, "last seen", ( current_time - dev.last_seen), "seconds ago" remove_list.append(dev) continue # Check if there is need for WDT update if current_time > dev.next_update and dev.next_update >= 0: dev.log.debug("UPDATING WDT!") dev.update_tries += 1 if dev.update_tries > 20: print "[" + dev.address + "] REMOVED due to", dev.update_tries, "WDT update retries" remove_list.append(dev) else: t1 = tlvlib.create_set_tlv32( 0, tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG, self.watchdog_time) try: # Retry every minute dev.next_update = current_time + 60 dev.send_tlv(t1) except Exception as e: print "[" + dev.address + "] FAILED TO UPDATE WDT!" print e if current_time >= dev.next_fetch and dev.next_fetch >= 0: dev.fetch_tries += 1 if self._fetch_periodic(dev): dev.fetch_tries = 0 dev.next_fetch = time.time() + self.fetch_time else: print "*** failed to fetch from", dev.address, "(" + str( dev.fetch_tries) + ")" # Try again a little later dev.next_fetch = time.time() + 10 * dev.fetch_tries for dev in remove_list: self.remove_device(dev.address) time.sleep(1)
def _process_get_response(self, tlv): if tlv.instance == 0: if tlv.variable == tlvlib.VARIABLE_UNIT_BOOT_TIMER: # Update the boot time estimation seconds,ns = tlvlib.convert_ieee64_time(tlv.int_value) last_boot_time = self.boot_time self.boot_time = self.last_seen - seconds # Assume reboot if the boot time backs at least 30 seconds if last_boot_time - self.boot_time > 30: self.log.info("REBOOT DETECTED!") elif tlv.variable == tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG: if self.next_update < 0: # Ignore watchdog in this device pass elif hasattr(tlv, 'int_value') and tlv.int_value > 0: self.log.debug("WDT updated! %d seconds remaining", tlv.int_value) self.next_update = self.last_seen + tlv.int_value - self._device_server.guard_time self.update_tries = 0 else: # Need to refresh watchdog t1 = tlvlib.create_set_tlv32(0, tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG, self._device_server.watchdog_time) self.send_tlv(t1) elif tlv.variable == tlvlib.VARIABLE_SLEEP_DEFAULT_AWAKE_TIME: # This node is a sleepy node self.set_sleepy_device() elif self.button_instance and tlv.instance == self.button_instance: if tlv.variable == tlvlib.VARIABLE_GPIO_TRIGGER_COUNTER: self.button_counter = tlv.int_value elif tlv.variable == tlvlib.VARIABLE_EVENT_ARRAY and tlv.op == tlvlib.TLV_EVENT_RESPONSE: self.log.info("button pressed - %d times",self.button_counter) # Rearm the button self.arm_device(self.button_instance) de = DeviceEvent(self, EVENT_BUTTON, self.button_counter) self._device_server.send_event(de) elif self.motion_instance and tlv.instance == self.motion_instance: if tlv.variable == 0x100: self.motion_counter, = struct.unpack("!q", tlv.data[8:16]) elif tlv.variable == tlvlib.VARIABLE_EVENT_ARRAY and tlv.op == tlvlib.TLV_EVENT_RESPONSE: self.log.info("MOTION! - %d times",self.motion_counter) # Rearm the button self.arm_device(self.motion_instance) de = DeviceEvent(self, EVENT_MOTION, self.motion_counter) self._device_server.send_event(de) elif self.nstats_instance and tlv.instance == self.nstats_instance: if tlv.variable == tlvlib.VARIABLE_NSTATS_DATA: self._handle_nstats(tlv) elif self.temperature_instance and tlv.instance == self.temperature_instance: if tlv.variable == tlvlib.VARIABLE_TEMPERATURE: temperature = (tlv.int_value - 273150) / 1000.0 self.log.info("Temperature: " + str(round(temperature, 2)) + " C")
def _manage_devices(self): while self.running: current_time = time.time() remove_list = [] for dev in self.get_devices(): # Check if there is need for discovery if not dev.is_discovered(): if dev.discovery_tries < 5: self.discover_device(dev) if not dev.is_discovered(): # Do a live check if needed... if dev.last_seen + 60 < current_time and dev.last_ping + 60 < current_time: self.ping(dev) # Remove non-discoverable devices after some time # so they can be tried again if dev.last_seen + 180 < current_time: print "Removing",dev.address,"last seen",(current_time - dev.last_seen),"seconds ago" remove_list.append(dev) continue # Check if there is need for WDT update if current_time > dev.next_update and dev.next_update >= 0: dev.log.debug("UPDATING WDT!") dev.update_tries += 1 if dev.update_tries > 20: print "[" + dev.address + "] REMOVED due to",dev.update_tries,"WDT update retries" remove_list.append(dev) else: t1 = tlvlib.create_set_tlv32(0, tlvlib.VARIABLE_UNIT_CONTROLLER_WATCHDOG, self.watchdog_time) try: # Retry every minute dev.next_update = current_time + 60 dev.send_tlv(t1) except Exception as e: print "[" + dev.address + "] FAILED TO UPDATE WDT!" print e if current_time >= dev.next_fetch and dev.next_fetch >= 0: dev.fetch_tries += 1 if self._fetch_periodic(dev): dev.fetch_tries = 0 dev.next_fetch = time.time() + self.fetch_time else: print "*** failed to fetch from", dev.address,"("+str(dev.fetch_tries)+")" # Try again a little later dev.next_fetch = time.time() + 10 * dev.fetch_tries for dev in remove_list: self.remove_device(dev.address) time.sleep(1)
def tlvlamp(ws, ip, led): de = ws.get_device_manager().get_device(ip) if de and de.lamp_instance: t1 = tlvlib.create_set_tlv32(de.lamp_instance, tlvlib.VARIABLE_LAMP_CONTROL, float(led)/100.0 * 0xffffffffL) try: enc, tlvs = tlvlib.send_tlv(t1, ip) if tlvs[0].error == 0: print "LAMP set to ", led, "%" else: print "LAMP Set error", tlvs[0].error except socket.timeout: print "LAMP No response from node", ip ws.sendMessage(json.dumps({"error":"No response from node " + ip}))
def tlvled(ws, ip, led): de = ws.get_device_manager().get_device(ip) if de and de.leds_instance: t1 = tlvlib.create_set_tlv32(de.leds_instance, tlvlib.VARIABLE_LED_TOGGLE, 1 << int(led)) try: enc, tlvs = tlvlib.send_tlv(t1, ip) if tlvs[0].error == 0: print "LED ", led, " toggle." else: print "LED Set error", tlvs[0].error except socket.timeout: print "LED No response from node", ip ws.sendMessage(json.dumps({"error":"No response from node " + ip}))
def tlvled(ws, ip, led): de = ws.get_device_manager().get_device(ip) if de and de.leds_instance: t1 = tlvlib.create_set_tlv32(de.leds_instance, tlvlib.VARIABLE_LED_TOGGLE, 1 << int(led)) try: enc, tlvs = tlvlib.send_tlv(t1, ip) if tlvs[0].error == 0: print "LED ", led, " toggle." else: print "LED Set error", tlvs[0].error except socket.timeout: print "LED No response from node", ip ws.sendMessage(json.dumps({"error": "No response from node " + ip}))
def send_upgrade(segment, size, instance, host, port): print "Upgrading ", segment[0] + 1, instance, len( segment[1]), " at ", segment[0] * size, "\b" * 35, sys.stdout.flush() t1 = tlvlib.create_set_tlv32(instance, tlvlib.VARIABLE_WRITE_CONTROL, tlvlib.FLASH_WRITE_CONTROL_WRITE_ENABLE) t2 = tlvlib.create_set_vector_tlv(instance, tlvlib.VARIABLE_FLASH, tlvlib.SIZE32, segment[0] * size / 4, len(segment[1]) / 4, segment[1]) try: enc, tlvs = tlvlib.send_tlv([t1, t2], host, port, 1.5) if enc.error != 0 or tlvs[0].error != 0 or tlvs[1].error != 0: print print "ERROR: failed to write image segment" return False except socket.timeout: return False return True
enc, tlvs = tlvlib.send_tlv([t1,t2, t3], host) tlv = tlvs[0] print "\tNetwork address: 0x" + binascii.hexlify(tlvs[2].value) print "\tRouting table size:",tlv.int_value," revision:",tlvs[1].int_value if tlv.int_value > 0: t = tlvlib.create_get_vector_tlv(i, tlvlib.VARIABLE_TABLE, tlvlib.SIZE512, 0, tlv.int_value) enc, tlvs = tlvlib.send_tlv(t, host) tlv = tlvs[0] for r in range(0, tlv.element_count): o = r * 64 IPv6Str = socket.inet_ntop(socket.AF_INET6, tlv.value[o:o+16]) IPv6LLStr = socket.inet_ntop(socket.AF_INET6, tlv.value[o+16:o+32]) print "\t",(r + 1), IPv6Str, "->", IPv6LLStr elif data[0] == tlvlib.INSTANCE_NEIGHBOURS: t1 = tlvlib.create_set_tlv32(i, tlvlib.VARIABLE_NBR_REVISION, 0) t2 = tlvlib.create_get_tlv32(i, tlvlib.VARIABLE_NBR_REVISION) t3 = tlvlib.create_get_tlv32(i, tlvlib.VARIABLE_NBR_COUNT) enc, tlvs = tlvlib.send_tlv([t1,t2, t3], host) nbr_rev = tlvs[1].int_value nbr_count = tlvs[2].int_value print "\tNeighbor table size:", nbr_count," revision:",nbr_rev if verbose and nbr_count > 0: if nbr_count > 10: # only list first 10 neighbors nbr_count = 10 t = tlvlib.create_get_vector_tlv(i, tlvlib.VARIABLE_NBR_TABLE, tlvlib.SIZE512, 0, nbr_count) # No need to check revision again since only a single read is done enc, tlvs = tlvlib.send_tlv(t, host) tlv = tlvs[0]
arg += 1 if arg < len(sys.argv): usage() instance = tlvlib.find_instance_with_type(host, tlvlib.INSTANCE_LEDS_GENERIC, verbose) if not instance: print "Could not find a leds instance in", host exit() ts = [] # Control leds via bit mask (only on/off) if op is not None: if led is not None: t = tlvlib.create_set_tlv32(instance, op, led) ts.append(t) t = tlvlib.create_get_tlv32(instance, tlvlib.VARIABLE_LED_CONTROL) ts.append(t) enc,tlvs = tlvlib.send_tlv(ts, host) t = tlvs[len(tlvs) - 1] if t.error == 0: print "Current leds:",bin(t.int_value) exit() # Control leds via states (supports multicolor leds) VARIABLE_LED_STATE = 0x105 if state is not None: t = tlvlib.create_set_vector_tlv(instance, VARIABLE_LED_STATE, tlvlib.SIZE32, led - 1, 1, struct.pack("!L", state))
import tlvlib, sys, struct, socket, binascii if len(sys.argv) < 2: print "Usage ", sys.argv[0], " <host> <intensity in percent>" exit(1) host = sys.argv[1] p = float(sys.argv[2]) if p > 100: print "Too high value 0 - 100" exit(1) print "Setting lamp to ", p d = tlvlib.discovery(host) i = 1 for data in d[1]: if data[0] == tlvlib.INSTANCE_LAMP: print "Found LAMP instnace, setting intensity." t1 = tlvlib.create_set_tlv32(i, 0x100, (p * 0.01) * 0xffffffff) enc,tlvs = tlvlib.send_tlv([t1], host) i = i + 1
if arg < len(sys.argv): usage() instance = tlvlib.find_instance_with_type(host, tlvlib.INSTANCE_LEDS_GENERIC, verbose) if not instance: print "Could not find a leds instance in", host exit() ts = [] # Control leds via bit mask (only on/off) if op is not None: if led is not None: t = tlvlib.create_set_tlv32(instance, op, led) ts.append(t) t = tlvlib.create_get_tlv32(instance, tlvlib.VARIABLE_LED_CONTROL) ts.append(t) enc, tlvs = tlvlib.send_tlv(ts, host) t = tlvs[len(tlvs) - 1] if t.error == 0: print "Current leds:", bin(t.int_value) exit() # Control leds via states (supports multicolor leds) VARIABLE_LED_STATE = 0x105 if state is not None: t = tlvlib.create_set_vector_tlv(instance, VARIABLE_LED_STATE, tlvlib.SIZE32, led - 1, 1, struct.pack("!L", state))
def set_location(self, address, location): self.log.debug("[%s] Setting location to %d", address, location) t = tlvlib.create_set_tlv32(0, tlvlib.VARIABLE_LOCATION_ID, location) enc,tlvs = tlvlib.send_tlv(t, address) return tlvs