def __init__(self, *args, **kwargs): super().__init__(args, kwargs) self._uart = None self._pps_pin = None if kwargs is not None: if 'gps_uart' in kwargs: self._uart = kwargs['gps_uart'] if 'pps_pin' in kwargs: self._pps_pin = kwargs['pps_pin'] if (self._uart == None): raise ValueError("need a uart for the gps") if (self._pps_pin == None): raise ValueError("need a pin that gps sends 1pps to us on") # we also need the RTC device self._rtc = RTC() self._pps_event = Event() self._rtc_ssr = uctypes.struct(_RTC_BASE + _RTC_SSR_OFFSET, self._rtc_ssr_struct, uctypes.NATIVE) self._rtc_dr = uctypes.struct(_RTC_BASE + _RTC_DR_OFFSET, self._rtc_dr_struct, uctypes.NATIVE) self._pps_rtc = 0 self._pps_discard = 0 self._ss_offset = -10000 self._refclk = (0, 0, 0, 0, 0, 0)
def __init__(self, pin, callback): self._ev_start = Event() self._callback = callback self._times = array('i', (0 for _ in range(self.edgecount + 1))) # 1 for overrun ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin) self._reset() loop = asyncio.get_event_loop() loop.create_task(self._run())
class NEC_IR(): edgecount = 68 block_time = 73 # 68.1ms nominal. Allow for some tx tolerance (?) def __init__(self, pin, callback): self._ev_start = Event() self._callback = callback self._times = array( 'i', (0 for _ in range(self.edgecount + 1))) # 1 for overrun ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin) self._reset() loop = asyncio.get_event_loop() loop.create_task(self._run()) def _reset(self): self._edge = 0 self._overrun = False self._ev_start.clear() async def _run(self): while True: await self._ev_start # Wait unitl data collection has started await asyncio.sleep_ms(self.block_time ) # Data block should have ended self._decode() # decode, clear event, prepare for new rx, call cb # Pin interrupt. Save time of each edge for later decode. def _cb_pin(self, line): if not self._overrun: # Overrun: ignore pulses until software timer times out if not self._ev_start.is_set(): # First edge received self._ev_start.set() self._times[self._edge] = ticks_us() if self._edge < self.edgecount: self._edge += 1 else: self._overrun = True # Overrun. decode() will test and reset def _decode(self): val = -3 if self._overrun else 0 if not self._overrun: width = ticks_diff(self._times[1], self._times[0]) if width > 4000: # 9ms leading mark for all valid data width = ticks_diff(self._times[2], self._times[1]) if width > 3000: # 4.5ms space for normal data if self._edge < self.edgecount: val = -1 # Haven't received the correct number of edges else: # Time spaces only (marks are identical) for edge_no in range(3, self.edgecount, 2): val &= 0x1fffffff # Constrain to 32 bit integer (b30 == b31) val <<= 1 # nos. will still be unique because of logical inverse address width = ticks_diff(self._times[edge_no + 1], self._times[edge_no]) if width > 1120: val += 1 elif width > 1700: # 2.5ms space for a repeat code. Should have exactly 4 edges. val = 1 if self._edge == 4 else -2 self._reset() self._callback(val)
def __init__(self, pin, callback): self._ev_start = Event() self._callback = callback self._times = array( 'i', (0 for _ in range(self.edgecount + 1))) # 1 for overrun pin.irq(handler=self._cb_pin, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING)) self._reset() loop = asyncio.get_event_loop() loop.create_task(self._run())
def __init__(self): # generic section self._log = core._log self._log.debug("Plugin: test contruction") self._utils = core._utils self._plugins = core._plugins self._lock = Event() # plugin specific section self.valuenames = {} self.valuenames["valueN1"] = "GPIO" self.valuenames["valueF1"] = "" self.valuenames["valueD1"] = 0 # release lock, ready for next measurement self._lock.clear()
async def run_event_test(): print('Test Lock class') loop = asyncio.get_event_loop() lock = Lock() loop.create_task(run_lock(1, lock)) loop.create_task(run_lock(2, lock)) loop.create_task(run_lock(3, lock)) print('Test Event class') event = Event() print('got here') loop.create_task(eventset(event)) print('gh1') await eventwait(event) # run_event_test runs fast until this point print('Event status {}'.format('Incorrect' if event.is_set() else 'OK')) print('Tasks complete')
def __init__(self) : # generic section self._log = core._log self._log.debug("Plugin: ds18 contruction") self._utils = core._utils self._plugins = core._plugins self._hal = core._hal self._lock = Event() # plugin specific section self.dxpin = dxpin self.valuenames["valueN1"]= "Temperature" self.valuenames["valueF1"]= "" self.valuenames["valueD1"]= 0 # release lock, ready for next measurement self._lock.clear()
def __init__(self, pin, callback, extended, *args): # Optional args for callback self._ev_start = Event() self._callback = callback self._extended = extended self._addr = 0 self.block_time = 80 if extended else 73 # Allow for some tx tolerance (?) self._args = args self._times = array('i', (0 for _ in range(_EDGECOUNT + 1))) # +1 for overrun if platform == 'pyboard': ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin) else: pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True) self._edge = 0 self._ev_start.clear() loop = asyncio.get_event_loop() loop.create_task(self._run())
def __init__(self): # generic section self._log = core._log self._log.debug("Plugin: bme280 contruction") self._utils = core._utils self._plugins = core._plugins self._lock = Event() # plugin specific section self.valuenames["valueN1"] = "Temperature" self.valuenames["valueN2"] = "Humidity" self.valuenames["valueN3"] = "Pressure" self.valuenames["valueF1"] = "" self.valuenames["valueF2"] = "" self.valuenames["valueF3"] = "" self.valuenames["valueD1"] = 0 self.valuenames["valueD2"] = 0 self.valuenames["valueD3"] = 0 # release lock, ready for next measurement self._lock.clear()
class LED_Flashable(): def __init__(self, loop, led_no): self.led = pyb.LED(led_no) self.event = Event() loop.create_task(self.flash_task()) def flash(self, period_ms): if self.event.is_set(): return self.event.set(period_ms) async def flash_task(self): while True: await self.event period_ms = self.event.value() self.event.clear() self.led.on() await asyncio.sleep_ms(period_ms) self.led.off()
async def run_ack(): loop = asyncio.get_event_loop() event = Event() ack1 = Event() ack2 = Event() count = 0 while True: loop.create_task(event_wait(event, ack1, 1)) loop.create_task(event_wait(event, ack2, 2)) event.set(count) count += 1 print('event was set') await ack1 ack1.clear() print('Cleared ack1') await ack2 ack2.clear() print('Cleared ack2') event.clear() print('Cleared event') await asyncio.sleep(1)
def __init__(self): self._log = core._log self._log.debug("Protocol: domoticz http contruction") self._lock = Event() # release lock, ready for next loop self._lock.clear()
class Copernicus_GPS(gps.GPS): _enable_sentences = { 'GGA': (1 << 0), 'GLL': (1 << 1), 'VTG': (1 << 2), 'GSV': (1 << 3), 'GSA': (1 << 4), 'ZDA': (1 << 5), 'RMC': (1 << 8), 'TF': (1 << 9), 'BA': (1 << 13) } class PPS_Mode: OFF = 0 ON = 1 FIX = 2 class PPS_Polarity: ACTIVE_LOW = 0 ACTIVE_HIGH = 1 # we have some special events for config apply def __init__(self, uart): super().__init__(uart) self._nm_ack = Event() self._ps_ack = Event() # Additional incoming message processing (on to of gps.py) # PTNLRNM - Automatic Message Output (Response) async def _rx_ptnlrnm(self, segs): self._nm_ack.set() return # PTNLRPS - PPS Configuration (Response) async def _rx_ptnlrps(self, segs): self._ps_ack.set() return async def set_auto_messages(self, types, interval): # compute bitmask to enable messages bitmask = 0 for type in types: bitmask |= self._enable_sentences[type] #print(bin(bitmask)) # send the command fmt = 'PTNLSNM,{:04x},{:02d}' #print(fmt.format(bitmask,interval)) print('gps: setting auto messages to', types, 'every', interval, 'seconds') await self._send(fmt.format(bitmask, interval)) # wait for ack print('gps: awaiting messages config ack') await self._nm_ack self._nm_ack.clear() print('gps: messages config accepted') return async def set_pps_mode(self, mode, length_ns, polarity, cable_ns): fmt = 'PTNLSPS,{},{},{},{}' # length is in 1/100th of ns length_ns = int(length_ns / 100) print('gps: setting PPS config') await self._send(fmt.format(mode, length_ns, polarity, cable_ns)) print('gps: awaiting ack to PPS config') await self._ps_ack self._ps_ack.clear() print('gps: PPS config accepted') return
def __init__(self): self._log = core._log self._log.debug("Protocol: openhab mqtt contruction") self._lock = Event() # release lock, ready for next loop self._lock.clear()
class switch_plugin: inputtype = "normal" # Default switch type datastore = None # Place where plugin data is stored for reboots def __init__(self): # generic section self._log = core._log self._log.debug("Plugin: switch contruction") self._utils = core._utils self._plugins = core._plugins self._hal = core._hal self._lock = Event() self.dxpin = dxpin # plugin specific section self.valuenames = {} self.valuenames["valueN1"] = "switch" self.valuenames["valueF1"] = "" self.valuenames["valueD1"] = 0 # release lock, ready for next measurement self._lock.clear() def init(self, plugin, device, queue, scriptqueue): self._log.debug("Plugin: switch init") # generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue) self.content = plugin.get('content', content) plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(self.devicename) # plugin specific section self.switch_status = bootstate if self.inputtype == 'normal': self._log.debug("Plugin: switch init normal, pin: " + self.dxpin) # Setup switch self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Switch(self.swpin) # Register coros to launch on contact close and open self.switch.close_func(self.asyncswitchopen) self.switch.open_func(self.asyncswitchclosed) elif self.inputtype == 'low': self._log.debug("Plugin: switch init low, pin: " + self.dxpin) # Setup button active low self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) else: self._log.debug("Plugin: switch init high, pin: " + self.dxpin) # Setup button active high self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_DOWN) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) return True def loadform(self, plugindata): self._log.debug("Plugin: switch loadform") # generic section self._utils.plugin_loadform(self, plugindata) # plugin specific section plugindata['inputtype'] = self.inputtype plugindata['dxpin0'] = self.dxpin def saveform(self, plugindata): self._log.debug("Plugin: switch saveform") # generic section self._utils.plugin_saveform(self, plugindata) # plugin specific section self.inputtype = plugindata['inputtype'] self.dxpin = plugindata['dxpin0'] # store values data = {} data["inputtype"] = self.inputtype data["dxpin"] = self.dxpin data["valueN1"] = self.valuenames["valueN1"] data["valueF1"] = self.valuenames["valueF1"] data["valueD1"] = self.valuenames["valueD1"] self._plugins.writestore(self.devicename, data) if self.inputtype == 'normal': # Setup switch self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Switch(self.swpin) # Register coros to launch on contact close and open self.switch.close_func(self.asyncswitchopen) self.switch.open_func(self.asyncswitchclosed) elif self.inputtype == 'low': # Setup button active low self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) else: # Setup button active high self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_DOWN) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) def read(self, values): self._log.debug("Plugin: switch read") # generic section values['valueN1'] = self.valuenames["valueN1"] values['valueD1'] = self.switch_status def write(self, values): self._log.debug("Plugin: switch write") async def asyncprocess(self): self._log.debug("Plugin: switch process") # plugin specific section # If a switch occured if self.switch_status: # send data to protocol and script/rule queues self.valuenames["valueD1"] = self.switch_status self._utils.plugin_senddata(self) # erase status self.switch_status = "" # release lock, ready for next measurement self._lock.clear() # #CUSTOM SENSOR CODE... # async def asyncswitchopen(self): self.switch_status = 'open' # release lock, ready for next measurement self._lock.clear() async def asyncswitchclosed(self): self.switch_status = 'closed' # release lock, ready for next measurement self._lock.clear() async def asyncbuttonpress(self): self.switch_status = 'press' # release lock, ready for next measurement self._lock.clear() async def asyncbuttonrelease(self): self.switch_status = 'release' # release lock, ready for next measurement self._lock.clear() async def asyncbuttondouble(self): self.switch_status = 'double' # release lock, ready for next measurement self._lock.clear() async def asyncbuttonlong(self): self.switch_status = 'long' # release lock, ready for next measurement self._lock.clear()
from gc import collect, mem_free from sys import platform from asyn import Event from homie import __version__, utils from homie.constants import (DEVICE_STATE, MAIN_DELAY, QOS, RESTORE_DELAY, SLASH, UNDERSCORE) from mqtt_as import MQTTClient from uasyncio import get_event_loop, sleep_ms from utime import time _EVENT = Event() def await_ready_state(func): def new_gen(*args, **kwargs): await _EVENT await func(*args, **kwargs) return new_gen class HomieDevice: """MicroPython implementation of the Homie MQTT convention for IoT.""" def __init__(self, settings): self._state = "init" self._stime = time() self.stats_interval = settings.DEVICE_STATS_INTERVAL self.nodes = [] self.callback_topics = {}
def __init__(self, loop, led_no): self.led = pyb.LED(led_no) self.event = Event() loop.create_task(self.flash_task())
class bme280_plugin: valuenames = {} datastore = None def __init__(self) : # generic section self._log = core._log self._log.debug("Plugin: bme280 contruction") self._utils = core._utils self._plugins = core._plugins self._lock = Event() # plugin specific section self.valuenames["valueV1"] = 0 # added by AJ self.valuenames["valueV2"] = 0 # added by AJ self.valuenames["valueV3"] = 0 # added by AJ self.valuenames["valueN1"]= "Temperature" self.valuenames["valueN2"]= "Humidity" self.valuenames["valueN3"]= "Pressure" self.valuenames["valueF1"]= "" self.valuenames["valueF2"]= "" self.valuenames["valueF3"]= "" self.valuenames["valueD1"]= 0 self.valuenames["valueD2"]= 0 self.valuenames["valueD3"]= 0 # release lock, ready for next measurement self._lock.clear() def init(self, plugin, device, queue, scriptqueue): self._log.debug("Plugin: bme280 init") # plugin generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue) self.content = plugin.get('content',content) self.pincnt = pincnt self.valuecnt = valuecnt self.stype = stype self.valuenames['devicename'] = device['name'] # gets device/plugin name, added AJ plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(device["name"]) # plugin specific section self.bme_elev = bme_elev self.i2c_addr = i2c_addr self.i2c = core._hal.get_i2c(i2c) if self.i2c != None: try: self._log.debug("Plugin: bme280 init i2c") self.bme280_init(address=self.i2c_addr) except OSError as e: self._log.debug("Plugin: bme280 init OSError exception: "+repr(e)) return False return True def loadform(self,plugindata): self._log.debug("Plugin: bme280 loadform") # generic section self._utils.plugin_loadform(self, plugindata) plugindata['i2c'] = i2c plugindata['i2c_addr'] = self.i2c_addr # plugin specific section plugindata['bme_elev'] = self.bme_elev def saveform(self,plugindata): self._log.debug("Plugin: bme280 saveform") # generic section self._utils.plugin_saveform(self, plugindata) sf_i2c = plugindata.get('i2c',None) if sf_i2c: self.sf_i2c = int(sf_i2c) else: self.sf_i2c = None sf_i2c_addr = plugindata.get('i2c_addr',None) if sf_i2c_addr: self.i2c_addr = int(sf_i2c_addr) else: self.i2c_addr = None # plugin specific section sf_bme_elev = plugindata.get('bme_elev',None) if sf_bme_elev: self.bme_elev = int(sf_bme_elev) else: self.bme_elev = None self.i2c = core._hal.get_i2c(i2c) if self.i2c: try: if self.i2c != None: self.bme280_init(address=self.i2c_addr) except OSError as e: self._log.debug("Plugin: bme280 saveform OSError exception: "+repr(e)) def read(self, values): self._log.debug("Plugin: bme280 read") # generic section values['valueN1'] = self.valuenames["valueN1"] values['valueN2'] = self.valuenames["valueN2"] values['valueN3'] = self.valuenames["valueN3"] #values['valueV1'] = round(self.valuenames["valueV1"], int(self.valuenames['valueD1']) ) # temp, specify decimal places #values['valueV2'] = round(self.valuenames["valueV2"], int(self.valuenames['valueD2']) ) # hum, specify decimal places #values['valueV3'] = round(self.valuenames["valueV3"], int(self.valuenames['valueD3']) ) # press, specify decimal places # plugin specific section if self.i2c != None: try: dvalues = self.bme280_values() #print("bme280.py l.153: dvalues =", dvalues) except Exception as e: self._log.debug("Plugin: bme280 read exception: "+repr(e)) values['valueV1'] = '' values['valueV2'] = '' values['valueV3'] = '' return values values["valueV1"] = round(float(dvalues[0]), int(self.valuenames['valueD1']) ) # temp, specify decimal places values["valueV2"] = round(float(dvalues[2]), int(self.valuenames['valueD2']) ) # hum, specify decimal places values["valueV3"] = round(float(dvalues[1]), int(self.valuenames['valueD3']) ) # press, specify decimal places else: self._log.debug("Plugin: BME280 read, empty values") # empty values values['valueV1'] = '' values['valueV2'] = '' values['valueV3'] = '' return values def write(self): self._log.debug("Plugin: bme280 write") async def asyncprocess(self): # plugin specific section self._log.debug("Plugin: bme280 process") if self.i2c: try: t, p, h = self.bme280_read_compensated_data() except Exception as e: self._log.debug("Plugin: bme280 process exception: "+repr(e)) # release lock, ready for next measurement self._lock.clear() return # send data to protocol and script/rule queues self.valuenames["valueV1"] = round(t/100, int(self.valuenames['valueD1']) ) # temp, specify decimal places self.valuenames["valueV2"] = round(h/1024, int(self.valuenames['valueD2']) ) # hum, specify decimal places self.valuenames["valueV3"] = round(p/25600, int(self.valuenames['valueD3']) ) # press, specify decimal places self._utils.plugin_senddata(self) # release lock, ready for next measurement self._lock.clear() # #CUSTOM SENSOR CODE... # def bme280_init(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, **kwargs): # Check that mode is valid. if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, BME280_OSAMPLE_8, BME280_OSAMPLE_16]: raise ValueError( 'Unexpected mode value {0}. Set mode to one of ' 'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or ' 'BME280_ULTRAHIGHRES'.format(mode)) self._mode = mode self.address = address # load calibration data dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26) dig_e1_e7 = self.i2c.readfrom_mem(self.address, 0xE1, 7) self.dig_T1, self.dig_T2, self.dig_T3, self.dig_P1, \ self.dig_P2, self.dig_P3, self.dig_P4, self.dig_P5, \ self.dig_P6, self.dig_P7, self.dig_P8, self.dig_P9, \ _, self.dig_H1 = unpack("<HhhHhhhhhhhhBB", dig_88_a1) self.dig_H2, self.dig_H3 = unpack("<hB", dig_e1_e7) e4_sign = unpack_from("<b", dig_e1_e7, 3)[0] self.dig_H4 = (e4_sign << 4) | (dig_e1_e7[4] & 0xF) e6_sign = unpack_from("<b", dig_e1_e7, 5)[0] self.dig_H5 = (e6_sign << 4) | (dig_e1_e7[4] >> 4) self.dig_H6 = unpack_from("<b", dig_e1_e7, 6)[0] self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL, bytearray([0x3F])) self.t_fine = 0 # temporary data holders which stay allocated self._l1_barray = bytearray(1) self._l8_barray = bytearray(8) self._l3_resultarray = array("i", [0, 0, 0]) def bme280_read_raw_data(self, result): """ Reads the raw (uncompensated) data from the sensor. Args: result: array of length 3 or alike where the result will be stored, in temperature, pressure, humidity order Returns: None """ self._l1_barray[0] = self._mode self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL_HUM, self._l1_barray) self._l1_barray[0] = self._mode << 5 | self._mode << 2 | 1 self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL, self._l1_barray) sleep_time = 1250 + 2300 * (1 << self._mode) sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 time.sleep_us(sleep_time) # Wait the required time # burst readout from 0xF7 to 0xFE, recommended by datasheet self.i2c.readfrom_mem_into(self.address, 0xF7, self._l8_barray) readout = self._l8_barray # pressure(0xF7): ((msb << 16) | (lsb << 8) | xlsb) >> 4 raw_press = ((readout[0] << 16) | (readout[1] << 8) | readout[2]) >> 4 # temperature(0xFA): ((msb << 16) | (lsb << 8) | xlsb) >> 4 raw_temp = ((readout[3] << 16) | (readout[4] << 8) | readout[5]) >> 4 # humidity(0xFD): (msb << 8) | lsb raw_hum = (readout[6] << 8) | readout[7] result[0] = raw_temp result[1] = raw_press result[2] = raw_hum def bme280_read_compensated_data(self, result=None): """ Reads the data from the sensor and returns the compensated data. Args: result: array of length 3 or alike where the result will be stored, in temperature, pressure, humidity order. You may use this to read out the sensor without allocating heap memory Returns: array with temperature, pressure, humidity. Will be the one from the result parameter if not None """ self.bme280_read_raw_data(self._l3_resultarray) raw_temp, raw_press, raw_hum = self._l3_resultarray # temperature var1 = ((raw_temp >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11) var2 = (((((raw_temp >> 4) - self.dig_T1) * ((raw_temp >> 4) - self.dig_T1)) >> 12) * self.dig_T3) >> 14 self.t_fine = var1 + var2 temp = (self.t_fine * 5 + 128) >> 8 # pressure var1 = self.t_fine - 128000 var2 = var1 * var1 * self.dig_P6 var2 = var2 + ((var1 * self.dig_P5) << 17) var2 = var2 + (self.dig_P4 << 35) var1 = (((var1 * var1 * self.dig_P3) >> 8) + ((var1 * self.dig_P2) << 12)) var1 = (((1 << 47) + var1) * self.dig_P1) >> 33 if var1 == 0: pressure = 0 else: p = 1048576 - raw_press p = (((p << 31) - var2) * 3125) // var1 var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25 var2 = (self.dig_P8 * p) >> 19 pressure = ((p + var1 + var2) >> 8) + (self.dig_P7 << 4) # humidity h = self.t_fine - 76800 h = (((((raw_hum << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) + 16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h * self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) * self.dig_H2 + 8192) >> 14)) h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4) h = 0 if h < 0 else h h = 419430400 if h > 419430400 else h humidity = h >> 12 if result: result[0] = temp result[1] = pressure result[2] = humidity return result return array("i", (temp, pressure, humidity)) def bme280_values(self): """ human readable values """ t, p, h = self.bme280_read_compensated_data() p = p // 256 pi = p // 100 pd = p - pi * 100 hi = h // 1024 hd = h * 100 // 1024 - hi * 100 return ("{}".format(t / 100), "{}.{:02d}".format(pi, pd), # edited AJ, remove non-numerics "{}.{:02d}".format(hi, hd))
def __init__(self, uart): super().__init__(uart) self._nm_ack = Event() self._ps_ack = Event()
class NEC_IR(): def __init__(self, pin, callback, extended, *args): # Optional args for callback self._ev_start = Event() self._callback = callback self._extended = extended self._addr = 0 self.block_time = 80 if extended else 73 # Allow for some tx tolerance (?) self._args = args self._times = array('i', (0 for _ in range(_EDGECOUNT + 1))) # +1 for overrun if platform == 'pyboard': ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin) else: # PR5962 ESP8266 hard IRQ's not supported pin.irq(handler=self._cb_pin, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING)) #elif ESP32: #pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING)) #else: #pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True) self._edge = 0 self._ev_start.clear() loop = asyncio.get_event_loop() loop.create_task(self._run()) async def _run(self): loop = asyncio.get_event_loop() while True: await self._ev_start # Wait until data collection has started # Compensate for asyncio latency latency = ticks_diff(loop.time(), self._ev_start.value()) await asyncio.sleep_ms(self.block_time - latency ) # Data block should have ended self._decode() # decode, clear event, prepare for new rx, call cb # Pin interrupt. Save time of each edge for later decode. def _cb_pin(self, line): t = ticks_us() # On overrun ignore pulses until software timer times out if self._edge <= _EDGECOUNT: # Allow 1 extra pulse to record overrun if not self._ev_start.is_set(): # First edge received loop = asyncio.get_event_loop() self._ev_start.set(loop.time()) # asyncio latency compensation self._times[self._edge] = t self._edge += 1 def _decode(self): overrun = self._edge > _EDGECOUNT val = OVERRUN if overrun else BADSTART if not overrun: width = ticks_diff(self._times[1], self._times[0]) if width > 4000: # 9ms leading mark for all valid data width = ticks_diff(self._times[2], self._times[1]) if width > 3000: # 4.5ms space for normal data if self._edge < _EDGECOUNT: # Haven't received the correct number of edges val = BADBLOCK else: # Time spaces only (marks are always 562.5µs) # Space is 1.6875ms (1) or 562.5µs (0) # Skip last bit which is always 1 val = 0 for edge in range(3, _EDGECOUNT - 2, 2): val >>= 1 if ticks_diff(self._times[edge + 1], self._times[edge]) > 1120: val |= 0x80000000 elif width > 1700: # 2.5ms space for a repeat code. Should have exactly 4 edges. val = REPEAT if self._edge == 4 else BADREP addr = 0 if val >= 0: # validate. Byte layout of val ~cmd cmd ~addr addr addr = val & 0xff cmd = (val >> 16) & 0xff if addr == ((val >> 8) ^ 0xff) & 0xff: # 8 bit address OK val = cmd if cmd == (val >> 24) ^ 0xff else BADDATA self._addr = addr else: addr |= val & 0xff00 # pass assumed 16 bit address to callback if self._extended: val = cmd if cmd == (val >> 24) ^ 0xff else BADDATA self._addr = addr else: val = BADADDR if val == REPEAT: addr = self._addr # Last valid addresss self._edge = 0 # Set up for new data burst and run user callback self._ev_start.clear() self._callback(val, addr, *self._args)
class test_plugin: gpiotype = "input" # Default GPIO type inputtype = "normal" # Default GPIO input type datastore = None # Place where plugin data is stored for reboots def __init__(self): # generic section self._log = core._log self._log.debug("Plugin: test contruction") self._utils = core._utils self._plugins = core._plugins self._lock = Event() # plugin specific section self.valuenames = {} self.valuenames["valueN1"] = "GPIO" self.valuenames["valueF1"] = "" self.valuenames["valueD1"] = 0 # release lock, ready for next measurement self._lock.clear() def init(self, plugin, device, queue, scriptqueue, rulequeue, valuequeue): self._log.debug("Plugin: test init") # generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue, rulequeue, valuequeue) self.content = plugin.get('content', content) self.pincnt = pincnt self.valuecnt = valuecnt self.stype = stype self.dtype = dtype self.valuenames['devicename'] = device[ 'name'] # gets device/plugin name, added AJ plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(name) return True def loadform(self, plugindata): self._log.debug("Plugin: test loadform") # generic section self._utils.plugin_loadform(self, plugindata) # plugin specific section plugindata['gpiotype'] = self.gpiotype plugindata['inputtype'] = self.inputtype def saveform(self, plugindata): self._log.debug("Plugin: test saveform") # generic section self._utils.plugin_saveform(self, plugindata) # plugin specific section self.gpiotype = plugindata['gpiotype'] self.inputtype = plugindata['inputtype'] self.dxpin = plugindata['dxpin0'] def read(self, values): self._log.debug("Plugin: test read") # generic section values['valueN1'] = self.valuenames["valueN1"] # plugin specific section values['valueV1'] = 'on' def write(self, values): self._log.debug("Plugin: test write") async def asyncprocess(self): self._log.debug("Plugin: test process") # send data to protocol and script/rule queues self.valuenames["valueV1"] = 'on' self._utils.plugin_senddata(self) # release lock, ready for next measurement self._lock.clear()
class ds18_plugin: valuenames = {} datastore = None roms = None def __init__(self) : # generic section self._log = core._log self._log.debug("Plugin: ds18 contruction") self._utils = core._utils self._plugins = core._plugins self._hal = core._hal self._lock = Event() # plugin specific section self.dxpin = dxpin self.valuenames["valueN1"]= "Temperature" self.valuenames["valueF1"]= "" self.valuenames["valueD1"]= 0 # release lock, ready for next measurement self._lock.clear() def init(self, plugin, device, queue, scriptqueue): self._log.debug("Plugin: ds18 init") # generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue) self.pincnt = pincnt self.valuecnt = valuecnt self.stype = stype self.content = plugin.get('content',content) self.dxpin = device.get('dxpin',dxpin) self._log.debug("Plugin: ds18 init dxpin"+self.dxpin) self.valuenames['devicename'] = device['name'] # gets device/plugin name, added AJ plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(device["name"]) # plugin specific section self._log.debug("Plugin: ds18 init, pin used: "+str(self.dxpin)) # the device is on Dx self.mPin = self._hal.pin(self.dxpin) if self.mPin: # create the onewire object self.ds18 = ds18x20.DS18X20(onewire.OneWire(self.mPin)) # scan for devices on the bus roms = self.ds18.scan() # scan for devices on the bus self.roms = self.ds18.scan() return True def loadform(self,plugindata): self._log.debug("Plugin: ds18 loadform") # generic section self._utils.plugin_loadform(self, plugindata) # plugin specific section plugindata['resolution']= resolution romcnt = 0 if not self.roms == None: for rom in self.roms: plugindata['rom'+str(romcnt)] = ''.join('{:02x}-'.format(x) for x in rom)[:-1] self._log.debug("Plugin: ds18 loadform, rom: "+plugindata['rom'+str(romcnt)]) romcnt+=1 else: self._log.debug("Plugin: ds18 loadform, no roms!") plugindata['romcnt'] = romcnt def saveform(self,plugindata): self._log.debug("Plugin: ds18 saveform") # generic section self._utils.plugin_saveform(self, plugindata) # plugin specific section self.romid = plugindata.get('deviceid','') self.resolution = plugindata['resolution'] # store values data = {} data["romid"] = self.romid data["dxpin"] = self.dxpin data["resolution"] = self.resolution data["valueN1"] = self.valuenames["valueN1"] data["valueF1"] = self.valuenames["valueF1"] data["valueD1"] = self.valuenames["valueD1"] self._plugins.writestore(self.devicename, data) # the device is on Dx self.mPin = self._hal.pin(self.dxpin) self._log.debug("Plugin: ds18 saveform, pin used: "+str(self.dxpin)) # create the onewire object self.ds18 = ds18x20.DS18X20(onewire.OneWire(self.mPin)) # scan for devices on the bus roms = self.ds18.scan() # scan for devices on the bus self.roms = self.ds18.scan() def read(self, values): self._log.debug("Plugin: ds18 read") # plugin specific section if not self.roms == None: for rom in self.roms: # Set convert on self.ds18.convert_temp() # wait 750ms for value to return #await asyncio.sleep_ms(750) import utime utime.sleep_ms(750) # Read temp values['valueN1'] = ''.join('{:02x}-'.format(x) for x in rom)[:-1] values["valueV1"] = round(self.ds18.read_temp(rom), int(self.valuenames['valueD1']) ) else: self._log.debug("Plugin: ds18 read, empty values") # dummy values values['valueN1'] = '' values["valueV1"] = '' def write(self, values): self._log.debug("Plugin: ds18 write") async def asyncprocess(self): self._log.debug("Plugin: ds18 process") # plugin specific section if not self.roms == None: for rom in self.roms: # Set convert on self.ds18.convert_temp() # wait 750ms for value to return await asyncio.sleep_ms(750) # put temperature value(s) in queue try: ds18temp = self.ds18.read_temp(rom) self._log.debug("Plugin: ds18 data read: "+str(ds18temp)) # send data to protocol and script/rule queues #self.valuenames["valueV1"] = ds18temp self.valuenames['valueV1'] = round(ds18temp, int(self.valuenames['valueD1']) ) self._utils.plugin_senddata(self) except Exception as e: self._log.debug("Plugin: ds18 readtemp failed! Error: "+repr(e)) # release lock, ready for next measurement self._lock.clear()
class openhab_mqtt_protocol: processcnt = 1 def __init__(self): self._log = core._log self._log.debug("Protocol: openhab mqtt contruction") self._lock = Event() # release lock, ready for next loop self._lock.clear() def init(self, protocol): self._log.debug("Protocol " + name + ": Init") self._client_id = protocol['client_id'] self._server = protocol['hostname'] self._port = protocol['port'] self._user = protocol['user'] self._password = protocol['password'] self._queue_out1 = {} self._queue_out2 = {} self._queue_out3 = {} self._queue_out = protocol[ 'publish'] #### was commented out AJ, now back in self._pubstr = protocol['publish'] #### added AJ self._queue_in = protocol['subscribe'] self._mq = MQTTClient(self._client_id, self._server, self._port, self._user, self._password) # Print diagnostic messages when retries/reconnects happens self._mq.DEBUG = True self._queue = queues.Queue(maxsize=100) return self._queue def connect(self): self._log.debug("Protocol: " + name + ": connect") return self._mq.reconnect() def disconnect(self): self._log.debug("Protocol: " + name + ": disconnect") self._mq.disconnect() def check(self): self._log.debug("Protocol: " + name + ": check") self._mq.check_msg() def status(self): self._log.debug("Protocol: " + name + ": status") self._mq.ping() def recieve(self): self._log.debug("Protocol: " + name + ": recieve") self._mq.subscribe(self.queue_in) def send(self, devicedata): self._log.debug("Protocol: " + name + ": send " + devicedata["stype"]) # connect or reconnect to mqtt server self.connect() mqttdata1 = None mqttdata2 = None mqttdata3 = None # case - all sensor types while True: mqttdata1 = None # looks like duplication of above! mqttdata1 = {} mqttdata2 = {} mqttdata3 = {} self._queue_out1 = '' self._queue_out2 = '' self._queue_out3 = '' message1 = '' message2 = '' message3 = '' # Get next plugin datavalues from utils.py, plugin_senddata(self, queuedata) try: devicedata['unitname'] = self._queue.get_nowait() devicedata['devicename'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol: " + name + " SENSOR_TYPE_SINGLE exception: " + repr(e)) break # case SENSOR_TYPE_SINGLE if devicedata["stype"] == core.SENSOR_TYPE_SINGLE: # get plugin values devicedata['valueV1'] = self._queue.get_nowait() devicedata['valueN1'] = self._queue.get_nowait() # Assemble mqtt message mqttdata1 = {} mqttdata1['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN1'] mqttdata1['msg'] = str(devicedata["valueV1"]) message1 = str(devicedata["valueV1"]) break # case SENSOR_TYPE_LONG if devicedata["stype"] == core.SENSOR_TYPE_LONG: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_LONG") break # case SENSOR_TYPE_DUAL if devicedata["stype"] == core.SENSOR_TYPE_DUAL: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_DUAL") break # case SENSOR_TYPE_TEMP_HUM if devicedata["stype"] == core.SENSOR_TYPE_TEMP_HUM: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_TEMP_HUM") # Get plugin values try: devicedata['valueV1'] = self._queue.get_nowait() devicedata['valueN1'] = self._queue.get_nowait() devicedata['valueV2'] = self._queue.get_nowait() devicedata['valueN2'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol: " + self._name + " SENSOR_TYPE_TEMP_HUM Exception: " + repr(e)) break # Assemble mqtt messages mqttdata1 = {} mqttdata1['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN1'] mqttdata1['msg'] = str(devicedata["valueV1"]) message1 = str(devicedata["valueV1"]) mqttdata2 = {} mqttdata2['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN2'] mqttdata2['msg'] = str(devicedata["valueV2"]) message1 = str(devicedata["valueV2"]) break # case SENSOR_TYPE_TEMP_BARO if devicedata["stype"] == core.SENSOR_TYPE_TEMP_BARO: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_TEMP_BARO") break # case SENSOR_TYPE_TEMP_HUM_BARO if devicedata["stype"] == core.SENSOR_TYPE_TEMP_HUM_BARO: #self._log.debug("Protocol: "+name+": SENSOR_TYPE_TEMP_HUM_BARO") # Get plugin values try: devicedata['valueV1'] = self._queue.get_nowait() devicedata['valueN1'] = self._queue.get_nowait() devicedata['valueV2'] = self._queue.get_nowait() devicedata['valueN2'] = self._queue.get_nowait() devicedata['valueV3'] = self._queue.get_nowait() devicedata['valueN3'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol: " + self._name + " SENSOR_TYPE_TEMP_HUM_BARO Exception: " + repr(e)) break # Assemble mqtt topics for valueV1, V2, V3 mqttdata1 = {} mqttdata1['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN1'] mqttdata1['msg'] = str(devicedata["valueV1"]) message1 = str(devicedata["valueV1"]) mqttdata2 = {} mqttdata2['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN2'] mqttdata2['msg'] = str(devicedata["valueV2"]) message2 = str(devicedata["valueV2"]) mqttdata3 = {} mqttdata3['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN3'] mqttdata3['msg'] = str(devicedata["valueV3"]) message3 = str(devicedata["valueV3"]) break # case SENSOR_TYPE_SWITCH if devicedata["stype"] == core.SENSOR_TYPE_SWITCH: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_SWITCH") # Get plugin values try: devicedata['valueV1'] = self._queue.get_nowait() devicedata['valueN1'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol: " + self._name + " SENSOR_TYPE_SWITCH Exception: " + repr(e)) break # Switches can have many values, OpenHAB (usually) only two: 1 (=on) or 0 (=off) switch_on = ['closed', 'press', 'double', 'long', 'on'] switch_off = ['open', 'release', 'off'] if devicedata["valueV1"] in switch_on: devicedata["valueV1"] = 1 elif devicedata["valueV1"] in switch_off: devicedata["valueV1"] = 0 else: break # Assemble mqtt message mqttdata1 = {} mqttdata1['topic'] = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN1'] mqttdata1['msg'] = str(devicedata["valueV1"]) message1 = str(devicedata["valueV1"]) break # case SENSOR_TYPE_DIMMER if devicedata["stype"] == core.SENSOR_TYPE_DIMMER: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_DIMMER") break # case SENSOR_TYPE_WIND if devicedata["stype"] == core.SENSOR_TYPE_WIND: self._log.debug("Protocol: " + name + ": SENSOR_TYPE_WIND") break # else UNKNOWN self._log.debug("Protocol " + name + ": Unknown sensor type!") break # Now publish the data to the MQTT broker/server # test for a user entry in webform protocol 'Publish' field; use it if it exists if self._pubstr != '': # entry exists in Publish field self._queue_out1 = self._pubstr self._queue_out2 = self._pubstr self._queue_out3 = self._pubstr else: # use "standard" format (unitname/devicename/valuename)... self._log.debug('Protocol: ' + name + ': "standard" topic format') self._queue_out1 = str(mqttdata1['topic']) if devicedata.get('valueN2') != None: self._queue_out2 = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN2'] if devicedata.get('valueN3') != None: self._queue_out3 = devicedata['unitname'] + "/" + devicedata[ 'devicename'] + "/" + devicedata['valueN3'] # Whichever the sensor type, check if we have mqtt data to send, and if so publish it # publish datavalue1... if message1 != None: self._log.debug("Protocol: " + name + " Publish: Topic: " + self._queue_out1 + ", Message: " + message1) self._mq.publish(self._queue_out1, message1) # publish datavalue2 (if it exists) if devicedata.get('valueN2') != None: if message2 != None: self._log.debug("Protocol: " + name + " Publish: Topic: " + self._queue_out2 + ", Message: " + message2) self._mq.publish(self._queue_out2, message2) # publish datavalue3 (if it exists) if devicedata.get('valueN3') != None: if mqttdata3['msg'] != None: self._log.debug("Protocol: " + name + " Publish: Topic: " + self._queue_out3 + ", Message: " + message3) self._mq.publish(self._queue_out3, message3) # we may eventually need more, for example for Dummy device (4 values)... # End of send # def process(self): # processing todo for protocol (main loop of protocol) self._log.debug("Protocol: " + name + " Processing...") devicedata = {} try: while True: message1 = self._queue.get_nowait( ) # keep reading from the protocol queue if message1 == core.QUEUE_MESSAGE_START: # found "start" message break # ready to read devicedata values devicedata['stype'] = self._queue.get_nowait() # get sensor type devicedata['serverid'] = self._queue.get_nowait() # get server id #print("OHmqtt l 266: devicedata = ", devicedata) self.send( devicedata ) # go and get other datavalues as needed, and publish them to MQTT ... except Exception as e: self._log.debug("Protocol: " + name + " process Exception: " + repr(e)) # release lock, ready for next processing self._lock.clear()
class domoticz_mqtt_protocol: processcnt = 1 def __init__(self): self._log = core._log self._log.debug("Protocol: domoticz mqtt contruction") self._lock = Event() # release lock, ready for next loop self._lock.clear() def init(self, protocol): self._log.debug("Protocol " + name + ": Init") self._client_id = protocol['client_id'] self._server = protocol['hostname'] self._port = protocol['port'] self._user = protocol['user'] self._password = protocol['password'] self._queue_out = protocol['publish'] self._queue_in = protocol['subscribe'] self._mq = MQTTClient(self._client_id, self._server, self._port, self._user, self._password) # Print diagnostic messages when retries/reconnects happens #self._mq.DEBUG = True self._queue = queues.Queue(maxsize=100) return self._queue def connect(self): self._log.debug("Protocol " + name + ": connect") return self._mq.reconnect() def disconnect(self): self._log.debug("Protocol " + name + ": disconnect") self._mq.disconnect() def check(self): self._log.debug("Protocol " + name + ": check") self._mq.check_msg() def status(self): self._log.debug("Protocol " + name + ": status") self._mq.ping() def recieve(self): self._log.debug("Protocol " + name + ": recieve") self._mq.subscribe(self.queue_in) def send(self, devicedata): self._log.debug("Protocol " + name + ": send " + devicedata["stype"]) # connect or reconnect to mqtt server self.connect() mqttdata = None # case while True: mqttdata = None # case SENSOR_TYPE_SINGLE if devicedata["stype"] == core.SENSOR_TYPE_SINGLE: self._log.debug("Protocol " + name + ": SENSOR_TYPE_SINGLE") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol " + name + " SENSOR_TYPE_SINGLE exception: " + repr(e)) break # Assemble mqtt message mqttdata = {} mqttdata["idx"] = devicedata["serverid"] mqttdata["nvalue"] = 0 mqttdata["svalue"] = str(devicedata["value1"]) message = ujson.dumps(mqttdata) break # case SENSOR_TYPE_LONG if devicedata["stype"] == core.SENSOR_TYPE_LONG: self._log.debug("Protocol " + name + ": SENSOR_TYPE_LONG") break # case SENSOR_TYPE_DUAL if devicedata["stype"] == core.SENSOR_TYPE_DUAL: self._log.debug("Protocol " + name + ": SENSOR_TYPE_DUAL") break # case SENSOR_TYPE_TEMP_HUM if devicedata["stype"] == core.SENSOR_TYPE_TEMP_HUM: self._log.debug("Protocol " + name + ": SENSOR_TYPE_TEMP_HUM") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() devicedata['value2'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol " + self._name + " SENSOR_TYPE_TEMP_HUM Exception: " + repr(e)) break # Assemble mqtt message mqttdata = {} mqttdata["idx"] = devicedata["serverid"] mqttdata["nvalue"] = 0 mqttdata["svalue"] = str(devicedata["value1"]) + ";" + str( devicedata["value2"]) + ";0" message = ujson.dumps(mqttdata) break # case SENSOR_TYPE_TEMP_BARO if devicedata["stype"] == core.SENSOR_TYPE_TEMP_BARO: self._log.debug("Protocol " + name + ": SENSOR_TYPE_TEMP_BARO") break # case SENSOR_TYPE_TEMP_HUM_BARO if devicedata["stype"] == core.SENSOR_TYPE_TEMP_HUM_BARO: self._log.debug("Protocol " + name + ": SENSOR_TYPE_TEMP_HUM_BARO") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() devicedata['value2'] = self._queue.get_nowait() devicedata['value3'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol " + self._name + " SENSOR_TYPE_TEMP_HUM_BARO Exception: " + repr(e)) break # Assemble mqtt message mqttdata = {} mqttdata["idx"] = devicedata["serverid"] mqttdata["nvalue"] = 0 mqttdata["svalue"] = str(devicedata["value1"]) + ";" + str( devicedata["value2"]) + ";0;" + str( devicedata["value3"]) + ";0" message = ujson.dumps(mqttdata) break # case SENSOR_TYPE_SWITCH if devicedata["stype"] == core.SENSOR_TYPE_SWITCH: self._log.debug("Protocol " + name + ": SENSOR_TYPE_SWITCH") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol " + self._name + " SENSOR_TYPE_SWITCH Exception: " + repr(e)) break # Switches can have many values, domoticz only two: on or off switch_on = ['closed', 'press', 'double', 'long'] switch_off = ['open', 'release'] if devicedata["value1"] in switch_on: devicedata["value1"] = 'On' elif devicedata["value1"] in switch_off: devicedata["value1"] = 'Off' else: break # Assemble mqtt message mqttdata = {} mqttdata["command"] = "switchlight" mqttdata["idx"] = devicedata["serverid"] mqttdata["switchcmd"] = devicedata["value1"] message = ujson.dumps(mqttdata) break # case SENSOR_TYPE_DIMMER if devicedata["stype"] == core.SENSOR_TYPE_DIMMER: self._log.debug("Protocol " + name + ": SENSOR_TYPE_DIMMER") break # case SENSOR_TYPE_WIND if devicedata["stype"] == core.SENSOR_TYPE_WIND: self._log.debug("Protocol " + name + ": SENSOR_TYPE_WIND") break # else UNKNOWN self._log.debug("Protocol " + name + ": Unknown sensor type!") break if mqttdata != None: self._log.debug("Protocol " + name + ": Message: " + message) self._mq.publish(self._queue_out, message) def process(self): # processing todo for protocol self._log.debug("Protocol " + name + " Processing...") devicedata = {} try: while True: message = self._queue.get_nowait() if message == core.QUEUE_MESSAGE_START: break devicedata['stype'] = self._queue.get_nowait() devicedata['serverid'] = self._queue.get_nowait() self.send(devicedata) except Exception as e: self._log.debug("Protocol " + name + " process Exception: " + repr(e)) # release lock, ready for next processing self._lock.clear()
class domoticz_http_protocol: processcnt = 1 def __init__(self): self._log = core._log self._log.debug("Protocol: domoticz http contruction") self._lock = Event() # release lock, ready for next loop self._lock.clear() def init(self, protocol): self._log.debug("Protocol " + name + ": Init") self._client_id = protocol['client_id'] self._server = protocol['hostname'] self._port = protocol['port'] self._user = protocol['user'] self._password = protocol['password'] self._queue = queues.Queue(maxsize=100) return self._queue def connect(self): self._log.debug("Protocol " + name + ": connect") def disconnect(self): self._log.debug("Protocol " + name + ": disconnect") def check(self): self._log.debug("Protocol " + name + ": check") def status(self): self._log.debug("Protocol " + name + ": status") def receive(self): self._log.debug("Protocol " + name + ": recieve") def send(self, devicedata): self._log.debug("Protocol " + name + ": send " + devicedata["stype"]) # Assemble server url message = None # case while True: # case SENSOR_TYPE_SINGLE if devicedata["stype"] == core.SENSOR_TYPE_SINGLE: self._log.debug("Protocol " + name + ": SENSOR_TYPE_SINGLE") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() except Exception: self._log.debug( "Protocol " + name + " SENSOR_TYPE_TEMP_HUM exception: Queue Emtpy!") break # Assemble http message message = "/json.htm?type=command¶m=udevice&idx=" + str( devicedata["serverid"]) + "&nvalue=0&svalue=" + str( devicedata["value1"]) + ";0" break # case SENSOR_TYPE_LONG if devicedata["stype"] == core.SENSOR_TYPE_LONG: self._log.debug("Protocol " + name + ": SENSOR_TYPE_LONG") break # case SENSOR_TYPE_DUAL if devicedata["stype"] == core.SENSOR_TYPE_DUAL: self._log.debug("Protocol " + name + ": SENSOR_TYPE_DUAL") break # case SENSOR_TYPE_TEMP_HUM if devicedata["stype"] == core.SENSOR_TYPE_TEMP_HUM: self._log.debug("Protocol " + name + ": SENSOR_TYPE_TEMP_HUM") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() devicedata['value2'] = self._queue.get_nowait() except Exception: self._log.debug( "Protocol " + name + " SENSOR_TYPE_TEMP_HUM exception: Queue Emtpy!") break # Assemble http message message = "/json.htm?type=command¶m=udevice&idx=" + str( devicedata["serverid"]) + "&nvalue=0&svalue=" + str( devicedata["value1"]) + str( devicedata["value2"]) + ";0" break # case SENSOR_TYPE_TEMP_BARO if devicedata["stype"] == core.SENSOR_TYPE_TEMP_BARO: self._log.debug("Protocol " + name + ": SENSOR_TYPE_TEMP_BARO") break # case SENSOR_TYPE_TEMP_HUM_BARO if devicedata["stype"] == core.SENSOR_TYPE_TEMP_HUM_BARO: self._log.debug("Protocol " + name + ": SENSOR_TYPE_TEMP_HUM_BARO") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() devicedata['value2'] = self._queue.get_nowait() devicedata['value3'] = self._queue.get_nowait() except Exception: self._log.debug( "Protocol " + name + " SENSOR_TYPE_TEMP_HUM_BARO exception: Queue Emtpy!") break # Assemble http message message = "/json.htm?type=command¶m=udevice&idx=" + str( devicedata["serverid"]) + "&nvalue=0&svalue=" + str( devicedata["value1"]) + str( devicedata["value2"]) + ";0;" + str( devicedata["value3"]) + ";0" break # case SENSOR_TYPE_SWITCH if devicedata["stype"] == core.SENSOR_TYPE_SWITCH: self._log.debug("Protocol " + name + ": SENSOR_TYPE_SWITCH") # Get plugin values try: devicedata['value1'] = self._queue.get_nowait() except Exception: self._log.debug( "Protocol " + name + " SENSOR_TYPE_SWITCH exception: Queue Emtpy!") break # Switches can have many values, domoticz only two: on or off switch_on = ['closed', 'press', 'double', 'long'] switch_off = ['open', 'release'] if devicedata["value1"] in switch_on: devicedata["value1"] = 'On' elif devicedata["value1"] in switch_off: devicedata["value1"] = 'Off' else: break # Assemble http message message = "/json.htm?type=command¶m=switchlight&idx=" + str( devicedata["serverid"] ) + "&switchcmd=" + devicedata["value1"] break # case SENSOR_TYPE_DIMMER if devicedata["stype"] == core.SENSOR_TYPE_DIMMER: self._log.debug("Protocol " + name + ": SENSOR_TYPE_DIMMER") break # case SENSOR_TYPE_WIND if devicedata["stype"] == core.SENSOR_TYPE_WIND: self._log.debug("Protocol " + name + ": SENSOR_TYPE_WIND") break # else UNKNOWN self._log.debug("Protocol " + name + ": Unknown sensor type!") break if message != None: self._log.debug("Protocol " + name + " message: " + "http://" + self._server + ":" + str(self._port) + message) # Send data try: response = urequests.get("http://" + self._server + ":" + str(self._port) + message) self._log.debug("Protocol " + name + " response: " + response.text) response.close() except OSError as e: self._log.debug("Protocol " + name + " Exception: " + repr(e)) #self._log.debug("Protocol "+name+" response: "+resp.read().decode("utf-8")) def process(self): # processing todo for protocol self._log.debug("Protocol " + name) devicedata = {} try: while self._queue.get_nowait() != core.QUEUE_MESSAGE_START: pass devicedata['stype'] = self._queue.get_nowait() devicedata['serverid'] = self._queue.get_nowait() except Exception as e: self._log.debug("Protocol " + name + " proces Exception: " + repr(e)) self.send(devicedata) # release lock, ready for next processing self._lock.clear()
import uasyncio from sys import stdin, stdout from io import BytesIO from binascii import unhexlify, hexlify from asyn import Event from m5stack import LCD, fonts, color565, SDCard, buttons, keyboard, qr from bitcoin.mnemonic import secure_mnemonic, WORD_LIST from bitcoin.hd import HDPrivateKey from bitcoin.tx import Tx from bitcoin.script import Script # globals lcd = LCD() SIGN_IT = Event() DONT_SIGN_IT = Event() SIGNED = Event() KEY = None PARTIAL_QR = '' last_qr = 0 KEYBOARD = keyboard.KeyboardDriver(cb_fall=lambda value: lcd.print(str(value))) async def qr_callback(b): # this is very hacky b/c qr driver will return parts of a qr code at-a-time # and i don't have a standard way to know that I have the whole thing (need checksum or something) # also, doesn't accept commands yet ... just transaction signing ... global PARTIAL_QR, last_qr if time.time() - last_qr > 1:
class ssd1306_plugin: datastore = None # Place where plugin data is stored for reboots def __init__(self) : # generic section self._log = core._log self._log.debug("Plugin: ssd1306 contruction") self._utils = core._utils self._plugins = core._plugins self._lock = Event() # plugin specific section self.valuenames = {} self.valuenames["valueN1"]= "" self.valuenames["valueF1"]= "" self.valuenames["valueD1"]= 0 # release lock, ready for next measurement self._lock.clear() def init(self, plugin, device, queue, scriptqueue): self._log.debug("Plugin: ssd1306 init") # generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue) self.content = plugin.get('content',content) self.pincnt = pincnt self.valuecnt = valuecnt self.stype = stype self.dtype = dtype self.ssd_i2c = ssd_i2c self.ssd_rotation = ssd_rotation self.ssd_width = ssd_width self.ssd_height = ssd_height self.ssd_timeout = ssd_timeout self.ssd_line1 = ssd_line1 self.ssd_line2 = ssd_line2 self.ssd_line3 = ssd_line3 self.ssd_line4 = ssd_line4 self.ssd_line5 = ssd_line5 self.ssd_line6 = ssd_line6 self.ssd_line7 = ssd_line7 self.ssd_line8 = ssd_line8 self._device = device plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(name) # Load values self._plugins.loadvalues(self._device,self.valuenames) # Set triggers self.triggers = name+"#"+self.valuenames["valueN1"] self._plugins.triggers(device, self.triggers) return True def loadform(self,plugindata): self._log.debug("Plugin: ssd1306 loadform") # generic section self._utils.plugin_loadform(self, plugindata) # plugin specific section plugindata["ssd_i2c"] = self.ssd_i2c plugindata["ssd_rotation"] = self.ssd_rotation plugindata["ssd_height"] = self.ssd_height plugindata["ssd_width"] = self.ssd_width plugindata["ssd_timeout"] = self.ssd_timeout def saveform(self,plugindata): self._log.debug("Plugin: ssd1306 saveform") # generic section self._utils.plugin_saveform(self, plugindata) # plugin specific section self._plugins.savevalues(self._device,self.valuenames) def read(self, values): self._log.debug("Plugin: ssd1306 read") # generic section values['valueN1'] = self.valuenames["valueN1"] # plugin specific section values['valueV1'] = 'on' def write(self, values): self._log.debug("Plugin: ssd1306 write") #print(values) async def asyncprocess(self): self._log.debug("Plugin: ssd1306 process") # send data to protocol and script/rule queues self.valuenames["valueV1"] = 'on' self._utils.plugin_senddata(self) # release lock, ready for next measurement self._lock.clear()
class SyncedClock_RTC(syncedclock.SyncedClock): # since pyb.RTC() is unreliable for reads, do it ourselves directly _RTC_BASE = const(0x40002800) _RTC_SSR_OFFSET = const(0x28) _rtc_ssr_struct = { "ss": 0 | uctypes.BFUINT32 | 0 << uctypes.BF_POS | 15 << uctypes.BF_LEN } _RTC_TR_OFFSET = const(0x00) _rtc_tr_struct = { "pm": 0 | uctypes.BFUINT32 | 22 << uctypes.BF_POS | 1 << uctypes.BF_LEN, "ht": 0 | uctypes.BFUINT32 | 20 << uctypes.BF_POS | 2 << uctypes.BF_LEN, "hu": 0 | uctypes.BFUINT32 | 16 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "mnt": 0 | uctypes.BFUINT32 | 12 << uctypes.BF_POS | 3 << uctypes.BF_LEN, "mnu": 0 | uctypes.BFUINT32 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "st": 0 | uctypes.BFUINT32 | 4 << uctypes.BF_POS | 3 << uctypes.BF_LEN, "su": 0 | uctypes.BFUINT32 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN } _RTC_DR_OFFSET = const(0x04) _rtc_dr_struct = { "yt": 0 | uctypes.BFUINT32 | 20 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "yu": 0 | uctypes.BFUINT32 | 16 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "wdu": 0 | uctypes.BFUINT32 | 13 << uctypes.BF_POS | 3 << uctypes.BF_LEN, "mt": 0 | uctypes.BFUINT32 | 12 << uctypes.BF_POS | 1 << uctypes.BF_LEN, "mu": 0 | uctypes.BFUINT32 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "dt": 0 | uctypes.BFUINT32 | 4 << uctypes.BF_POS | 2 << uctypes.BF_LEN, "du": 0 | uctypes.BFUINT32 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN } _RTC_MAX = const(8191) # wrap initialiser def __init__(self, *args, **kwargs): super().__init__(args, kwargs) self._uart = None self._pps_pin = None if kwargs is not None: if 'gps_uart' in kwargs: self._uart = kwargs['gps_uart'] if 'pps_pin' in kwargs: self._pps_pin = kwargs['pps_pin'] if (self._uart == None): raise ValueError("need a uart for the gps") if (self._pps_pin == None): raise ValueError("need a pin that gps sends 1pps to us on") # we also need the RTC device self._rtc = RTC() self._pps_event = Event() self._rtc_ssr = uctypes.struct(_RTC_BASE + _RTC_SSR_OFFSET, self._rtc_ssr_struct, uctypes.NATIVE) self._rtc_dr = uctypes.struct(_RTC_BASE + _RTC_DR_OFFSET, self._rtc_dr_struct, uctypes.NATIVE) self._pps_rtc = 0 self._pps_discard = 0 self._ss_offset = -10000 self._refclk = (0, 0, 0, 0, 0, 0) # try to get some better perf out of this, it's staticish code @micropython.native def _pps(self, p): # grab RTC data when we tick # we need to pull this directly out of the registers because we don't want to # allocate ram, and the RTC() module does self._pps_rtc = self._rtc_ssr.ss # need to read DR to nothing to unlock shadow registers self._pps_discard = self._rtc_dr.du self._pps_event.set() return async def _wait_gpslock(self): try: while True: if (self._gps.isLocked()): return True await asyncio.sleep(1) except asyncio.TimeoutError: print("syncedclock_rtc: failed to get lock, reinit gps") return False async def _wait_pps(self): try: await self._pps_event self._pps_event.clear() return True except asyncio.TimeoutError: print("syncedclock_rtc: failed to get pps event in time") return False # this will now be running in a thread, safe to do things which block async def _calibration_loop(self): # start RTC print("syncedclock_rtc: start rtc") self._rtc.init() # initalise gps self._gps = GPS(self._uart) ppsint = ExtInt(self._pps_pin, ExtInt.IRQ_RISING, Pin.PULL_NONE, self._pps) ppsint.disable() self._pps_event.clear() await asyncio.sleep(0) while True: print("syncedclock_rtc: initalise gps") await self._gps.set_auto_messages(['RMC'], 1) await self._gps.set_pps_mode(GPS.PPS_Mode.FIX, 42, GPS.PPS_Polarity.ACTIVE_HIGH, 0) print("syncedclock_rtc: waiting for gps lock (30s)") res = await asyncio.wait_for(self._wait_gpslock(), 30) if (res == False): continue print( "syncedclock_rtc: gps locked, start pps interrupt and wait for pps (3s)" ) #self._pps_pin.irq(trigger=Pin.IRQ_RISING, handler=self._pps) ppsint.enable() res = await asyncio.wait_for(self._wait_pps(), 3) if (res == False): print( "syncedclock_rtc: pps signal never recieved, bad wiring?") print("syncedclock_rtc: terminating") return # PPS signal leads GPS data by about half a second or so # so the GPS data contains the *previous* second at this point # add 1 second and reset RTC print("syncedclock_rtc: pps pulse recieved, set RTC clock") date = self._gps.date() time = self._gps.time() # helpfully utime and pyb.RTC use different order in the tuple now = utime.localtime( utime.mktime((date[2], date[1], date[0], time[0], time[1], time[2], 0, 0)) + 1) self._rtc.datetime( (now[0], now[1], now[2], 0, now[3], now[4], now[5], 0)) print("syncedclock_rtc: rtc clock now", self._rtc.datetime()) await asyncio.sleep(0) print("syncedclock_rtc: calibration loop started") # ensure we ignore the first cycle last_rtc_ss = -1 # count 32 seconds and calculate the error count = 0 tick_error = 0 while True: # each time we get an PPS event, work out the ticks difference res = await asyncio.wait_for(self._wait_pps(), 3) if (res == False): print("syncedclock_rtc: lost pps signal, restarting") self._locked = False #self._pps_pin.irq(handler=None) ppsint.disable() break rtc_ss = self._pps_rtc await asyncio.sleep(0) # first pass, just discard the value if (last_rtc_ss == -1): last_rtc_ss = rtc_ss continue await asyncio.sleep(0) count += 1 # compute the difference in ticks between this and the last error = (rtc_ss - last_rtc_ss) if (abs(error) > _RTC_MAX - 50): # probably actually rollover problem if (rtc_ss < last_rtc_ss): error = (rtc_ss + _RTC_MAX + 1 - last_rtc_ss) else: error = (rtc_ss - last_rtc_ss + _RTC_MAX + 1) await asyncio.sleep(0) #print(error) tick_error += (error) last_rtc_ss = rtc_ss # always use the last top of second as current offset if it's not a huge error # when locked if (self._locked and tick_error > -1 and tick_error < 1): self._ss_offset = rtc_ss await asyncio.sleep(0) if (count == 32): # if the tick error is +/-1 ticks, it's locked enough # we're only then about 3.81ppm but that's close enough if (self._locked == True and (tick_error > 1 or tick_error < -1)): print("syncedclock_rtc: lost lock") self._locked = False await asyncio.sleep(0) if (self._locked == False and (tick_error <= 1 and tick_error >= -1)): print("syncedclock_rtc: locked with", self._rtc.calibration()) # only cache top of second when we enter lock #self._ss_offset = (_RTC_MAX-rtc_ss) self._locked = True await asyncio.sleep(0) if (self._locked == True): # update reference clock point self._refclk = self._rtc.datetime() await asyncio.sleep(0) if (self._locked == False): print("syncedclock_rtc: error now", tick_error) # the total ticks missing should be applied to the calibration # we do this continously so we can ensure the clock is always remaining in sync await asyncio.sleep(0) try: self._rtc.calibration(self._rtc.calibration() + tick_error) except: print("syncedclock_rtc: error too large, ignoring") # allow us to to be interrupted now await asyncio.sleep(0) #print(rtc.calibration()) count = 0 tick_error = 0 def _rtc_to_unixtime(self, rtc_tuple, rtc_offset): ts = utime.mktime(( rtc_tuple[0], # year rtc_tuple[1], # month rtc_tuple[2], # day rtc_tuple[4], # hour rtc_tuple[5], # minute rtc_tuple[6], # second 0, 0)) + 946684800 # weekday and dayofyear are ignored tss = (_RTC_MAX - rtc_tuple[7]) + rtc_offset if tss >= _RTC_MAX: tss -= _RTC_MAX + 1 ts += 1 if tss < 0: tss += _RTC_MAX + 1 ts -= 1 return (ts, tss << 19) def now(self): if not self._locked: return None return self._rtc_to_unixtime(self._rtc.datetime(), self._ss_offset) def refclk(self): if not self._locked: return None return self._rtc_to_unixtime(self._refclk, self._ss_offset) async def start(self): super().start() loop = asyncio.get_event_loop() loop.create_task(self._calibration_loop()) print("syncedclock_rtc: calibration loop created") await asyncio.sleep(0) return