class DisplayWebThing(Thing): # regarding capabilities refer https://iot.mozilla.org/schemas # there is also another schema registry http://iotschema.org/docs/full.html not used by webthing def __init__(self, name: str, description: str, lcd: BaseCharLCD): Thing.__init__(self, 'urn:dev:ops:lcddisplay-1', 'Display ' + name + ' Controller', ['Display'], description) self.display = Display(lcd, self.__update_text) self.display_text = Value("") self.add_property( Property(self, 'displayed_text', self.display_text, metadata={ 'title': 'Displayed text', 'type': 'string', 'description': 'Displayed text', 'readOnly': True, })) self.upper_layer_text = Value( "", self.display.panel(Display.LAYER_UPPER).update_text) self.add_property( Property(self, 'upper_layer_text', self.upper_layer_text, metadata={ 'title': 'Upper layer text', 'type': 'string', 'description': 'The text of the upper layer', 'readOnly': False, })) self.upper_layer_text_ttl = Value( -1, self.display.panel(Display.LAYER_UPPER).update_ttl) self.add_property( Property( self, 'upper_layer_text_ttl', self.upper_layer_text_ttl, metadata={ 'title': 'Upper layer text (time-to-live)', 'type': 'integer', 'description': 'The time-to-live of the upper layer. Value -1 deactivates ttl', 'readOnly': False, })) self.middle_layer_text = Value( "", self.display.panel(Display.LAYER_MIDDLE).update_text) self.add_property( Property(self, 'middle_layer_text', self.middle_layer_text, metadata={ 'title': 'Middle layer text', 'type': 'string', 'description': 'The text of the middle layer', 'readOnly': False, })) self.middle_layer_text_ttl = Value( -1, self.display.panel(Display.LAYER_MIDDLE).update_ttl) self.add_property( Property( self, 'middle_layer_text_ttl', self.middle_layer_text_ttl, metadata={ 'title': 'Middle layer text (time-to-live)', 'type': 'integer', 'description': 'The time-to-live of the middle layer. Value -1 deactivates ttl', 'readOnly': False, })) self.lower_layer_text = Value( "", self.display.panel(Display.LAYER_LOWER).update_text) self.add_property( Property(self, 'lower_layer_text', self.lower_layer_text, metadata={ 'title': 'Lower layer text', 'type': 'string', 'description': 'The text of the lower layer', 'readOnly': False, })) self.lower_layer_text_ttl = Value( -1, self.display.panel(Display.LAYER_LOWER).update_ttl) self.add_property( Property( self, 'lower_layer_text_ttl', self.lower_layer_text_ttl, metadata={ 'title': 'Lower layer text (time-to-live)', 'type': 'integer', 'description': 'The time-to-live of the lower layer. Value -1 deactivates ttl', 'readOnly': False, })) self.ioloop = tornado.ioloop.IOLoop.current() def __update_text(self): self.ioloop.add_callback(self.__update_text_props) def __update_text_props(self): self.display_text.notify_of_external_update(self.display.text) self.upper_layer_text.notify_of_external_update( self.display.panel(Display.LAYER_UPPER).text) self.upper_layer_text_ttl.notify_of_external_update( self.display.panel(Display.LAYER_UPPER).ttl) self.middle_layer_text.notify_of_external_update( self.display.panel(Display.LAYER_MIDDLE).text) self.middle_layer_text_ttl.notify_of_external_update( self.display.panel(Display.LAYER_MIDDLE).ttl) self.lower_layer_text.notify_of_external_update( self.display.panel(Display.LAYER_LOWER).text) self.lower_layer_text_ttl.notify_of_external_update( self.display.panel(Display.LAYER_LOWER).ttl)
class ExtEnvironSensor(Thing): """An external environment sensor which updates every few seconds.""" global h def __init__(self, tbsense): Thing.__init__( self, 'urn:dev:ops:my-tb-thing-1234', 'My Thunderboard Sense Thing', [ 'TemperatureSensor', 'MultiLevelSensor', 'MultiLevelSensor', 'MultiLevelSensor', 'MultiLevelSensor', 'MultiLevelSensor', 'MultiLevelSensor' ], 'A web connected environment sensor') self.tbsense = tbsense #temperature sensor self.temp = Value(0.0) self.add_property( Property(self, 'temperature', self.temp, metadata={ '@type': 'TemperatureProperty', 'title': 'Temperature', 'type': 'number', 'description': 'The ambient temperature in C', 'minimum': -40.0, 'maximum': 100.0, 'unit': 'Celsius', 'readOnly': True, 'multipleOf': 0.1, })) #humidity sensor self.humidity = Value(0.0) self.add_property( Property(self, 'humidity', self.humidity, metadata={ '@type': 'LevelProperty', 'title': 'Humidity', 'type': 'number', 'description': 'The level of rel. humidity', 'minimum': 0, 'maximum': 100, 'unit': '%', 'readOnly': True, 'multipleOf': 0.1, })) #ambient light sensor # self.amb_light = Value(0.0) # self.add_property( # Property(self, 'ambient light', self.amb_light, # metadata={ # '@type': 'LevelProperty', # 'title': 'Ambient Light', # 'type': 'number', # 'description': 'The level of ambient light', # 'minimum': 0, # 'maximum': 100000, # 'unit': 'lux', # 'readOnly': True, # })) #UV index # self.uv_index = Value(0.0) # self.add_property( # Property(self, 'UV index', self.uv_index, # metadata={ # '@type': 'LevelProperty', # 'title': 'UV index', # 'type': 'number', # 'description': 'The level of UV index', # 'minimum': 0, # 'maximum': 50, # 'readOnly': True, # })) #barometric pressure self.pressure = Value(0.0) self.add_property( Property(self, 'pressure', self.pressure, metadata={ '@type': 'LevelProperty', 'title': 'Barometric pressure', 'type': 'number', 'description': 'The level of barometric pressure', 'minimum': 0, 'maximum': 1.2, 'unit': 'atm', 'readOnly': True, 'multipleOf': 0.01, })) #CO2 level self.co2 = Value(0) self.add_property( Property(self, 'co2', self.co2, metadata={ '@type': 'LevelProperty', 'title': 'CO2 level', 'type': 'number', 'description': 'The level of CO2', 'minimum': 0, 'maximum': 5000, 'unit': 'ppm', 'readOnly': True, })) #VOC level self.voc = Value(0) self.add_property( Property(self, 'voc', self.voc, metadata={ '@type': 'LevelProperty', 'title': 'VOC content', 'type': 'number', 'description': 'VOC content of air', 'minimum': 0, 'maximum': 5000, 'unit': 'ppb', 'readOnly': True, })) #Connection state self.connctd = Value(False) self.add_property( Property(self, 'connctd', self.connctd, metadata={ '@type': 'OnOffProperty', 'title': 'Connection', 'type': 'boolean', 'description': 'Conection status to Thunderboard', 'readOnly': True, })) syslog.syslog('Starting the sensor update looping task') self.enviro_task = get_event_loop().create_task(self.update_TbSense()) async def update_TbSense(self): while True: try: if self.tbsense.getConnState() == 'conn': temp = self.tbsense.readTemperature() - 6.0 self.temp.notify_of_external_update(temp) self.humidity.notify_of_external_update( self.tbsense.readHumidity()) # self.amb_light.notify_of_external_update(self.tbsense.readAmbientLight()) # self.uv_index.notify_of_external_update(self.tbsense.readUvIndex()) self.co2.notify_of_external_update(self.tbsense.readCo2()) self.voc.notify_of_external_update(self.tbsense.readVoc()) self.pressure.notify_of_external_update( round(self.tbsense.readPressure() / 1000, 2)) self.connctd.notify_of_external_update(True) await sleep(h) else: self.connctd.notify_of_external_update(False) raise BTLEDisconnectError("Connection lost!") except (BTLEDisconnectError, BTLEInternalError): syslog.syslog('Trying to reconnect...') while True: try: #try to reconnect same device await sleep(1) self.tbsense.peri.connect(self.tbsense.dev.addr, self.tbsense.dev.addrType) self.tbsense.storeCharacteristics() except: continue else: syslog.syslog('Reconnected!') self.connctd.notify_of_external_update(True) break except CancelledError: break def cancel_tasks(self): self.enviro_task.cancel() get_event_loop().run_until_complete(self.enviro_task)
class LedStrip(Thing): """A LED-Strip in the entry of my upper Level""" def __init__(self, _location, _main_loop): self.location = _location self.main_loop = _main_loop self.id = f'urn:dev:ops:{self.location}-vorraum-led' self.name = f'{self.location}-LED_Strip' Thing.__init__(self, self.id, self.name, ['OnOffSwitch', 'Light'], 'A web connected LED-Strip') # GPIO18 (P26) pwm on Linkit Smart 7688 self.pwm = mraa.Pwm(26) self.pwm.period_us(20000) # 20ms period ==> 50Hz self.pwm.enable(True) # Start sending PWM signal # relay2 (P18) on Linkit Smart 7688 self.relay2 = mraa.Gpio(18) # relay1 (P19) on Linkit Smart 7688 self.relay1 = mraa.Gpio(19) self.relay2.dir(mraa.DIR_OUT) # set as OUTPUT pin # set as INPUT pin, its a pullup, so its High when the switch is open. self.relay1.dir(mraa.DIR_IN) self.relay1_read() # get initial Value of Relay1 self.r1_previous = False self.main_loop_time = None self.async_timeout = None self.locality = LocationInfo('Zürich', 'Switzerland', 'Europe/Zurich', 47.39, 8.07) logging.info( f'Information for {self.locality.name}/{self.locality.region}, ' f'Timezone: {self.locality.timezone}, ' f'Latitude: {self.locality.latitude:.02f}; ' f'Longitude: {self.locality.longitude:.02f}') self.day_time_start = sun.sunrise( self.locality.observer, date=datetime.now(), tzinfo=self.locality.timezone) - timedelta(minutes=30) logging.debug(f'LedStrip: day_time_start:{self.day_time_start}') self.day_time_stop = sun.sunset( self.locality.observer, date=datetime.now(), tzinfo=self.locality.timezone) + timedelta(minutes=30) logging.debug(f'LedStrip: day_time_stop:{self.day_time_stop}') self.state = Value(self.get_state(), self.toggle_digitalswitch) self.add_property( Property(self, 'digitalswitch', self.state, metadata={ '@type': 'OnOffProperty', 'title': f'{self.name}-digitalswitch', 'type': 'boolean', 'description': 'Whether the Strip is turned on', })) self.brightness = Value(self.get_brightness(), self.set_brightness) self.add_property( Property(self, 'brightness', self.brightness, metadata={ '@type': 'LevelProperty', 'title': 'Helligkeit', 'type': 'integer', 'description': 'The level of light from 0-100%', 'minimum': 0, 'maximum': 100, 'unit': 'percent', })) self.add_available_action( 'fade', { 'title': 'Helligkeitswert über eine Zeitdauer einstellen', 'description': 'Fade the lamp to a given level', 'input': { 'type': 'object', 'required': [ 'brightness', 'duration', ], 'properties': { 'brightness': { 'type': 'integer', 'minimum': 0, 'maximum': 100, 'unit': 'percent', }, 'duration': { 'type': 'integer', 'minimum': 1, 'unit': 'milliseconds', }, }, }, }, FadeLedStrip) self.motion_detection_delay = Value(self.get_motion_detection_delay(), self.set_motion_detection_delay) self.add_property( Property(self, 'motion_detection_delay', self.motion_detection_delay, metadata={ '@type': 'LevelProperty', 'title': 'Verzögertes Aus bei Bewegung (in Minuten)', 'type': 'integer', 'description': 'The delay in minutes', 'minimum': 0, 'maximum': 20, 'unit': 'minutes', })) self.motion_detection_active = Value( self.get_motion_detection_active(), self.set_motion_detection_active) self.add_property( Property(self, 'motion_detection_active', self.motion_detection_active, metadata={ '@type': 'BooleanProperty', 'title': 'Auf Bewegung reagieren?', 'type': 'boolean', 'description': 'Set Motion detection active or not', })) self.motion_detection_follower = Value(self.get_motion(), self.set_motion) self.add_property( Property(self, 'motion_detection_follower', self.motion_detection_follower, metadata={ '@type': 'MotionProperty', 'title': 'Bewegungs Sensor', 'type': 'boolean', 'description': 'motion=true, nomotion=false', })) self.timer = tornado.ioloop.PeriodicCallback(self.get_r1, 1000) self.timer.start() def get_brightness(self): """get the level from mraa.pwm""" brightness = round(self.pwm.read() * 100) logging.debug(f'LedStrip: get_brightness is set to: {brightness}') return brightness def set_brightness(self, brightness): """set the level with mraa""" self.pwm.write(round((brightness / 100), 2)) led_on = self.get_property('digitalswitch') if brightness < 1 and led_on is True: self.set_property('digitalswitch', False) elif brightness >= 1 and led_on is False: self.set_property('digitalswitch', True) logging.info(f'LedStrip: Set Brightness to {brightness}') return brightness def relay1_read(self): relay1 = bool(self.relay1.read()) if relay1 is True: relay1 = False elif relay1 is False: relay1 = True return relay1 def get_r1(self): """ only if footswitch changes """ r1 = self.relay1_read() if r1 != self.r1_previous: state = self.get_state() # if state: # self.fade_brightness_up(self.get_property('brightness'), 4000, 80) # else: # self.fade_brightness_down(self.get_property('brightness'), 4000, 0) self.state.notify_of_external_update(state) self.r1_previous = r1 def get_state(self): """ The manual switch is connected to a multiway switch made of two Relays with 3-ways. https://en.wikipedia.org/wiki/Multiway_switching#Traveler_system """ footswitch = bool(self.relay1_read()) digitalswitch = bool(self.relay2.read()) state = footswitch ^ digitalswitch logging.info(f'LedStrip: get_state: is set to {state}') return state def toggle_digitalswitch(self, state): """ switch to turn on/off LedStrip. """ s = self.relay2.read() self.relay2.write(not s) logging.info('LedStrip: toggle_digitalswitch called ' f'with state:{state} set to {s}') def motion(self): """ MOTION SENSOR calls this when ever it triggers """ logging.debug('LedStrip: motion: starts') date_time_now = datetime.now().time() logging.debug('LedStrip: motion: called self.date_time_now:' f'{date_time_now}') day_start = self.day_time_start.time() logging.debug(f'LedStrip: motion: called day_start:{day_start}') day_end = self.day_time_stop.time() logging.debug(f'LedStrip: motion: called day_end:{day_end}') if date_time_now > day_start and date_time_now < day_end: self.day_time = True logging.debug('LedStrip: motion: called during the Day') else: self.day_time = False logging.debug('LedStrip: motion: called in the Night') if not self.day_time: motion_active = self.get_property('motion_detection_active') logging.debug('LedStrip: motion: called while motion_active:' f'{motion_active}') if motion_active: logging.debug('LedStrip: motion: called on not day_time ' 'and Motion was activated, future add_callback ' 'awaits interrupt_call_back now') self.main_loop.add_callback(self.interrupt_call_back) else: logging.debug('LedStrip: motion: Motion is not activated') logging.debug('LedStrip: motion: end') def interrupt_call_back(self): logging.info('LedStrip: interrupt_call_back: starts, ' f'async_timeout:{self.async_timeout}') if self.async_timeout: self.main_loop.remove_timeout(self.async_timeout) logging.debug('LedStrip: interrupt_call_back: timeout was removed,' f' async_timeout:{self.async_timeout}') digitalswitch = self.get_property('digitalswitch') if digitalswitch: logging.debug(f'LedStrip: interrupt_call_back: ' f'digitalswitch is {digitalswitch} ' 'light is already ON') else: logging.debug(f'LedStrip: interrupt_call_back: ' f'digitalswitch is {digitalswitch} ' 'light now turns ON') #self.set_brightness(self, 1) self.set_property('digitalswitch', True) delay_seconds = self.get_delay_seconds() timeout_delta = self.main_loop.time() + delay_seconds timeout_delta_human = time.strftime('%H:%M:%S', time.gmtime(timeout_delta)) logging.debug(f'LedStrip: interrupt_call_back:' f'Light will stay on for {delay_seconds}s ' f'and turns OFF at:{timeout_delta_human}') self.async_timeout = self.main_loop.add_timeout( timeout_delta, self.interrupt_call_timeout) logging.debug('LedStrip: interrupt_call_back: end') def interrupt_call_timeout(self): logging.info('LedStrip: interrupt_call_timeout: called') digitalswitch = self.get_property('digitalswitch') footswitch = self.relay1_read() if (digitalswitch) and (not footswitch): self.set_property('digitalswitch', False) logging.debug('LedStrip: interrupt_call_timeout: ' f'async_timeout: {self.async_timeout}') self.main_loop.remove_timeout(self.async_timeout) logging.debug('LedStrip: interrupt_call_timeout ' f'async_timeout removed: {self.async_timeout}') self.async_timeout = False def fade_brightness_up(self, brightness_now, duration, brightness_after): steps = brightness_after - brightness_now if steps < 1: steps = 1 if steps > 100: steps = 100 delay_ms = duration / steps while brightness_after > self.get_property('brightness'): self.set_property('brightness', self.get_property('brightness') + 1) time.sleep(delay_ms / 1000) def fade_brightness_down(self, brightness_now, duration, brightness_after): steps = brightness_now - brightness_after if steps < 1: steps = 1 if steps > 100: steps = 100 delay_ms = duration / steps while brightness_after < self.get_property('brightness'): self.set_property('brightness', self.get_property('brightness') - 1) time.sleep(delay_ms / 1000) def get_delay_seconds(self): delay_minutes = self.get_property('motion_detection_delay') delay_seconds = delay_minutes * 60 logging.debug(f'LedStrip: get_delay_seconds is {delay_seconds}') return delay_seconds def get_motion(self): logging.debug('LedStrip: get_motion: get_motion_follower') value = self.get_property('motion_detection_follower') if value is None: logging.debug(f'LedStrip: get_motion: ' f'get_motion_detection_follower is {value}') self.set_property('motion_detection_follower', False) value = self.get_property('motion_detection_follower') logging.debug( f'LedStrip: get_motion: get_motion_detection_follower is {value}') return value def set_motion(self, value): if value: logging.debug('LedStrip: set_motion before set_motion_follower ' f'(LedStrip): {value}') self.motion() logging.debug('LedStrip: set_motion after set_motion_follower ' f'(LedStrip): {value}') else: logging.debug('LedStrip: set_motion is False we do nothing more ' f'(LedStrip) set_motion: {value}') def get_motion_detection_active(self): value = self.get_property('motion_detection_active') if value is None: logging.info(f'LedStrip: get_motion_detection_active: ' f'setting: True because {value}') return True return value def set_motion_detection_active(self, value): logging.info(f'LedStrip: set_motion_detection_active to {value}') def get_motion_detection_delay(self): value = self.get_property('motion_detection_delay') if value is None: logging.info( f'get_motion_detection_delay setting to 2 because {value}') return 2 return value def set_motion_detection_delay(self, value): logging.info(f'LedStrip: set_motion_detection_delay to {value}') """ END OF LED STRIP THING """ def cancel_led_strip_async_tasks(self): logging.info('LedStrip: stopping the status update loop task') self.timer.stop()
class VorraumNode(Thing): """A node in the entry of my upper Level""" def __init__(self, _location, _w1_device_id_list): self.location = _location self.id = f'urn:dev:ops:{self.location}-vorraum-node' self.name = f'{self.location}-node_functions' self.w1_device_id_list = _w1_device_id_list Thing.__init__(self, self.id, self.name, ['EnergyMonitor'], 'A web connected node') self.ina219 = ina219.INA219(busnum=0, address=0x40) self.power = Value(0.0) self.add_property( Property(self, f'{self.name}-power', self.power, metadata={ '@type': 'InstantaneousPowerProperty', 'title': f'{self.name}-Power', 'type': 'float', 'multipleOf': 0.01, 'description': 'the power used by this node', })) self.volt = Value(0.0) self.add_property( Property(self, f'{self.name}-voltage', self.volt, metadata={ '@type': 'VoltageProperty', 'title': f'{self.name}-Voltage', 'type': 'float', 'multipleOf': 0.01, 'description': 'the voltage used by this node', })) self.current = Value(0.0) self.add_property( Property(self, f'{self.name}-current', self.current, metadata={ '@type': 'CurrentProperty', 'title': f'{self.name}-Current', 'type': 'float', 'multipleOf': 0.01, 'description': 'the current used by this node', })) self.temperature = Value(0.0) self.add_property( Property(self, f'{self.name}-Temperature', self.temperature, metadata={ '@type': 'TemperatureProperty', 'title': f'{self.name}-Temperature', 'type': 'float', 'multipleOf': 0.01, 'description': 'the temperature in the case', })) self.timer = tornado.ioloop.PeriodicCallback(self.get_sensors, 300000) self.timer.start() def get_sensors(self): self.get_power() self.get_temperature() def get_power(self): logging.info("get_power") try: bus_voltage = self.ina219.get_bus_voltage_mV() self.volt.notify_of_external_update(bus_voltage / 1000) curent = self.ina219.get_current_mA() self.current.notify_of_external_update(curent / 1000) milliwats = self.ina219.get_power_mW() self.power.notify_of_external_update(milliwats / 1000) except AssertionError as e: logging.error(repr(e)) def get_temperature(self): logging.info('get_temperature') number_of_device_ids = len(self.w1_device_id_list) if number_of_device_ids < 1: logging.error('get_temperature:no w1 device detected') return for device in self.w1_device_id_list: logging.info(f'get_temperature:reading w1 device {device}. ' f'{number_of_device_ids} to been read') temperature = self.get_temperature_read_one(device) self.temperature.notify_of_external_update(temperature) def get_temperature_read_one(self, temp_sensor_id): try: logging.info(f'get_temperature_read_one of {temp_sensor_id}') # read 1-wire slave file from a specific device file_name = "/sys/bus/w1/devices/" + temp_sensor_id + "/w1_slave" file = open(file_name) filecontent = file.read() file.close() # read temperature values and convert to readable float stringvalue = filecontent.split("\n")[1].split(" ")[9] sensorvalue = float(stringvalue[2:]) / 1000 temperature = '%6.2f' % sensorvalue return temperature except Exception: logging.warn('get_temperature_read_one: ' f'not able to read from: {temp_sensor_id}') def cancel_node_async_tasks(self): logging.info('stopping the node update loop task') self.timer.stop()
class WeatherstationBME680(Thing): def __init__(self): Thing.__init__(self, 'Indoor Weatherstation', ['MultiLevelSensor', 'TemperatureSensor'], 'A web connected weatherstation') self.level = Value(0.0) self.add_property( Property(self, 'level', self.level, metadata={ '@type': 'LevelProperty', 'title': 'Air Quality', 'type': 'number', 'description': 'The current air quality', 'minimum': 0, 'maximum': 100, 'unit': 'percent', 'readOnly': True, })) self.humidity = Value(0.0) self.add_property( Property(self, 'humidity', self.humidity, metadata={ 'title': 'Humidity', 'type': 'number', 'description': 'Humidity in %', 'minimum': 0, 'maximum': 100, 'unit': 'percent', 'readOnly': True, })) self.temperature = Value(0.0) self.add_property( Property(self, 'temperature', self.temperature, metadata={ '@type': 'TemperatureProperty', 'title': 'Temperature', 'type': 'number', 'description': 'The current temperature', 'minimum': -20, 'maximum': 80, 'unit': 'degree celsius', 'readOnly': True, })) self.pressure = Value(0.0) self.add_property( Property(self, 'pressure', self.pressure, metadata={ 'title': 'Air Pressure', 'type': 'number', 'description': 'The current air pressure', 'minimum': 600, 'maximum': 1200, 'unit': 'hPa', 'readOnly': True, })) logging.debug('starting the sensor update looping task') self.timer = tornado.ioloop.PeriodicCallback(self.update_levels, 3000) self.timer.start() def update_levels(self): if sensorBME680.sensor.get_sensor_data(): new_level = sensorBME680.update_air_quality() logging.debug('setting new air quality: %s', new_level) self.level.notify_of_external_update(new_level) new_humidity = sensorBME680.update_humidity() logging.debug('setting new humidity: %s', new_humidity) self.humidity.notify_of_external_update(new_humidity) new_temperature = sensorBME680.update_temperature() logging.debug('setting new temperature: %s', new_temperature) self.temperature.notify_of_external_update(new_temperature) new_pressure = sensorBME680.update_pressure() logging.debug('setting new air pressure: %s', new_pressure) self.pressure.notify_of_external_update(new_pressure) def cancel_update_level_task(self): self.timer.stop()
class MotionSensor(Thing): # regarding capabilities refer https://iot.mozilla.org/schemas # there is also another schema registry http://iotschema.org/docs/full.html not used by webthing def __init__(self, gpio_number, name, description): Thing.__init__(self, 'urn:dev:ops:motionSensor-1', 'Motion ' + name + ' Sensor', ['MotionSensor'], description) self.gpio_number = gpio_number GPIO.setmode(GPIO.BCM) GPIO.setup(self.gpio_number, GPIO.IN) GPIO.add_event_detect(self.gpio_number, GPIO.BOTH, callback=self.__update, bouncetime=5) self.is_motion = False self.motion = Value(False) self.add_property( Property(self, 'motion', self.motion, metadata={ '@type': 'MotionProperty', 'title': 'Motion detected', "type": "boolean", 'description': 'Whether ' + name + ' motion is detected', 'readOnly': True, })) self.last_motion = Value(datetime.now().isoformat()) self.add_property( Property(self, 'motion_last_seen', self.last_motion, metadata={ 'title': 'Motion last seen', "type": "string", 'unit': 'datetime', 'description': 'The ISO 8601 date time of last movement', 'readOnly': True, })) self.ioloop = tornado.ioloop.IOLoop.current() def __update(self, channel): if GPIO.input(self.gpio_number): logging.info("motion detected") self.ioloop.add_callback(self.__update_motion_prop, True) else: self.ioloop.add_callback(self.__update_motion_prop, False) def __update_motion_prop(self, is_motion): if is_motion: self.motion.notify_of_external_update(True) self.last_motion.notify_of_external_update( datetime.now().isoformat()) else: self.motion.notify_of_external_update(False)
class AnwingWebThing(Thing): # regarding capabilities refer https://iot.mozilla.org/schemas # there is also another schema registry http://iotschema.org/docs/full.html not used by webthing def __init__(self, description: str, awning: Awning): Thing.__init__(self, 'urn:dev:ops:anwing-TB6612FNG', 'Awning ' + awning.name + " Controller", ['MultiLevelSensor'], description) self.awning = awning self.awning.register_listener(WebThingAwningPropertyListener(self)) self.target_position = Value(0, self.__target_position) self.add_property( Property(self, 'target_position', self.target_position, metadata={ '@type': 'LevelProperty', 'title': 'Awning target position', "type": "integer", "minimum": 0, "maximum": 100, "unit": "percent", 'description': 'awning target position' })) self.current_position = Value(0) self.add_property( Property(self, 'current_position', self.current_position, metadata={ '@type': 'LevelProperty', 'title': 'Awning current position', "type": "integer", 'minimum': 0, 'maximum': 100, "unit": "percent", 'readOnly': True, 'description': 'awning current position' })) self.retracting = Value(0) self.add_property( Property(self, 'retracting', self.retracting, metadata={ '@type': 'BooleanProperty', 'title': 'Awning is retracting', "type": "boolean", 'readOnly': True, 'description': 'Awning is retracting' })) self.extending = Value(0) self.add_property( Property(self, 'extending', self.extending, metadata={ '@type': 'BooleanProperty', 'title': 'Awning is extending', "type": "boolean", 'readOnly': True, 'description': 'Awning is extending' })) self.ioloop = tornado.ioloop.IOLoop.current() def __target_position(self, new_postion): self.awning.set_target_position(new_postion) def set_current_position(self, value): self.current_position.notify_of_external_update(value) logging.debug(self.awning.name + " position " + str(value) + " reached (target=" + str(self.target_position.get()) + ")") def set_retracting(self, value): self.retracting.notify_of_external_update(value) def set_extending(self, value): self.extending.notify_of_external_update(value)
class DhtSensor(Thing): # regarding capabilities refer https://iot.mozilla.org/schemas # there is also another schema registry http://iotschema.org/docs/full.html not used by webthing def __init__(self, gpio_number: int, description: str): Thing.__init__(self, 'urn:dev:ops:dhtSensor-1', 'Humidity and Temperature Sensor', ['TemperatureSensor', 'HumiditySensor'], description) self.sensor = Adafruit_DHT.DHT22 self.gpio_number = gpio_number self.humidity = Value(0.0) self.add_property( Property(self, 'humidity', self.humidity, metadata={ '@type': 'HumidityProperty', 'title': 'Humidity', 'type': 'number', 'description': 'The current humidity from 0%-100%', 'minimum': 0, 'maximum': 100, 'unit': 'percent', 'readOnly': True, })) self.temperature = Value(0) self.add_property( Property(self, 'temperature', self.temperature, metadata={ '@type': 'TemperatureProperty', 'title': 'Temperature', 'type': 'number', 'description': 'The current temperature', 'unit': 'degree celsius', 'readOnly': True, })) self.timer = tornado.ioloop.PeriodicCallback(self.__measure, (60 * 1000)) # 1 min self.timer.start() def __measure(self): try: humidity, temperature = Adafruit_DHT.read_retry( self.sensor, self.gpio_number) if humidity is not None: self.humidity.notify_of_external_update(round(humidity, 1)) logging.debug('humidity ' + str(humidity)) if temperature is not None: self.temperature.notify_of_external_update( round(temperature, 1)) logging.debug('temperature ' + str(temperature)) except Exception as e: logging.error(e) def cancel_measure_task(self): self.timer.stop()
class SenseHatThingSensor(Thing): """A Thing controlling Sensors of SenseHat""" def __init__(self): Thing.__init__(self, 'urn:dev:ops:my-sense-hat-sensor-1234', 'SenseHat Sensor', [], 'A web connected sense hat') controller.set_imu_config(True, True, True) self.pitch = Value(0.0) self.add_property( Property(self, 'pitch', self.pitch, metadata={ 'title': 'Pitch', 'type': 'number', 'description': 'Angle pitch', 'unit': 'd', 'minimum': 0, 'maximum': 360, 'readOnly': True, })) self.roll = Value(0.0) self.add_property( Property(self, 'roll', self.roll, metadata={ 'title': 'Roll', 'type': 'number', 'description': 'Angle', 'unit': 'd', 'minimum': 0, 'maximum': 360, 'readOnly': True, })) self.yaw = Value(0.0) self.add_property( Property(self, 'yaw', self.yaw, metadata={ 'title': 'Yaw', 'type': 'number', 'description': 'Angle', 'unit': 'd', 'minimum': 0, 'maximum': 360, 'readOnly': True, })) logging.debug('info: starting the sensor update looping task') self.timer = tornado.ioloop.PeriodicCallback(self.update_properties, 1000) self.timer.start() def update_properties(self): orientation = controller.get_orientation() self.pitch.notify_of_external_update(orientation['pitch']) self.roll.notify_of_external_update(orientation['roll']) self.yaw.notify_of_external_update(orientation['yaw']) def cancel_update_properties_task(self): self.timer.stop()