Esempio n. 1
0
def setup_gps():
    time.sleep(2)
    gc.enable()

    rtc = RTC()
    rtc.ntp_sync("pool.ntp.org")
    utime.sleep_ms(750)
    print('\nRTC Set from NTP to UTC:', rtc.now())
    utime.timezone(7200)
    print('Adjusted from UTC to EST timezone', utime.localtime(), '\n')
    if rtc.now()[0] == 1970:
        print("Datetime could not be automatically set")
        date_str = (input(
            'Enter datetime as list separated by commas (y, m, d, h, min, s): '
        )).split(',')
        date_str = tuple([int(item) for item in date_str])
        try:
            rtc.init(date_str)
            print('Time successfully set to ', rtc.now(), '\n')
        except Exception:
            print("Failed to set time...")
    py = Pytrack()
    l76 = L76GNSS(py, timeout=30)
    print("GPS Timeout is {} seconds".format(30))
    chrono = Timer.Chrono()
    chrono.start()

    # while (True):
    #     coord = l76.coordinates(debug=True)
    #     print("{} - {} - {}".format(coord, rtc.now(), gc.mem_free()))
    return l76
Esempio n. 2
0
def sync_rtc(rtcserver):
    #a.st1.ntp.br
    #b.st1.ntp.br
    #c.st1.ntp.br
    #d.st1.ntp.br
    #a.ntp.br
    #b.ntp.br
    #c.ntp.br
    #gps.ntp.br
    #pool.ntp.org

    from machine import RTC
    from time import sleep
    print("Syncing RTC...")
    rtc = RTC()
    print(rtc.now())

    rtc.ntp_sync(rtcserver)
    sleep(1)

    while not rtc.synced():
        print("Still syncing RTC...")
        rtc.ntp_sync(rtcserver)
        sleep(5)

    print(rtc.now())
    print("RTC Synchronized.\n")
def setRTCLocalTime():
    rtc = RTC()
    print("Time before sync: ", rtc.now())
    rtc.ntp_sync("pool.ntp.org")
    while not rtc.synced():
        utime.sleep(1)
        print("Waiting for NTP server...")
    print('\nTime after sync: ', rtc.now())
Esempio n. 4
0
def rtc_init():
    global rtc_synced
    rtc = RTC()
    rtc.ntp_sync('pool.ntp.org', update_period=15)
    print('Waiting for RTC/NTP sync...')

    chrono = Timer.Chrono()
    chrono.start()

    while not rtc.synced():
        # wait for 30 seconds, then give up and try manual NTP sync
        if chrono.read() > 30:
            print('Sync timed out after %s seconds...' % chrono.read())
            rtc.ntp_sync(None)
            break

        time.sleep(1)

    if rtc.synced():
        print('RTC Set from NTP daemon to UTC:', rtc.now())
        rtc_synced = True

    else:
        print('Fetching time from NTP server manually...')
        try:
            NTP_QUERY = bytearray(48)
            NTP_QUERY[0] = 0x1b
            addr = socket.getaddrinfo('pool.ntp.org', 123)[0][-1]
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.settimeout(3)
            s.sendto(NTP_QUERY, addr)
            msg = s.recv(48)
            s.close()

            # 70 years difference between NTP and Pycom epoch
            val = struct.unpack("!I", msg[40:44])[0] - 2208988800
            tm = time.localtime(val)
            rtc.init(tm)
            rtc_synced = True
            gc.collect()

        except socket.timeout:
            print('Timed out while fetching time from remote server.')

    if not rtc.synced() and rtc_synced:
        print('RTC Set from manual NTP call to UTC:', rtc.now())

    # adjust timezone
    if rtc_synced:
        # UTC-7/MST for testing
        time.timezone(-7*60*60)
        print('RTC adjusted from UTC to local timezone:', time.localtime())

    else:
        print('Unable to set RTC', rtc.now())
        print('Resetting NTP sync to 15 minutes')
        rtc.ntp_sync('pool.ntp.org', 60*15)
Esempio n. 5
0
def rtc_ntp_sync(TZ=0, timeout_s = 30):
    from machine import RTC
    print("sync rtc via ntp, TZ=", TZ)
    rtc = RTC()
    print("synced?", rtc.synced())
    rtc.ntp_sync('nl.pool.ntp.org')
    print("synced?", rtc.synced())
    #time.sleep_ms(750)
    time.timezone(TZ * 3600)

    timeout_ms = 1000 * timeout_s
    for i in range(0, timeout_ms):
        if rtc.synced():
            print("rtc is synced after", i/1000, "s")
            # if rtc.now()[0] == 1970:
            #     print()
            break
        if i % 100 == 0:
            print(".", end="")
        time.sleep_ms(1)
    if not rtc.synced():
        raise Exception("RTC did not sync in", timeout_ms/1000, "s")

    print("rtc.now", rtc.now())
    print("time.gmtime", time.gmtime())
    print("time.localtime", time.localtime())
    print("gmt  ", end=" ")
    pretty_gmt()
    print("local", end=" ")
    pretty_local()
Esempio n. 6
0
class SimpleLogger(object):
    LOGGER_NAME = "LOG"

    # stack inspection is not possible on micropython
    # might want to be able to add a socket as print target for remote / headless logging

    def __init__(self, logger_name="LOG"):
        self.level = _level
        self.LOGGER_NAME = logger_name
        self.rtc = RTC()

    def _level_str(self, level):
        if level in _level_dict:
            return _level_dict[level]
        return "LVL" + str(level)

    def log_hex(self, caller, message, data):
        if isinstance(data, bytearray):
            hexstr = [hex(c) for c in data]
        elif isinstance(data, bytes):
            hexstr = [hex(int(c)) for c in data]
        elif hasattr(data, '__iter__'):
            hexstr = [hex(c) for c in data]
        else:
            hexstr = '0x{0:02x}'.format(data)

        self.log(caller, DEBUG, "{} :{}".format(message, hexstr))

    def debug(self, caller, msg):
        self.log(caller, DEBUG, msg)

    def info(self, caller, msg):
        self.log(caller, INFO, msg)

    def warning(self, caller, msg):
        self.log(caller, WARNING, msg)

    def error(self, caller, msg):
        self.log(caller, ERROR, msg)

    def critical(self, caller, msg):
        self.log(caller, CRITICAL, msg)

    def log(self, caller, level, message):
        if level >= self.level:
            # t = utime.localtime()
            t = self.rtc.now()
            print(
                "[{}:{}]{}-{:02d}-{:02d} {:02d}:{:02d}:{:02d},{:04d} - {}: {}".format(self.LOGGER_NAME,
                                                                                      self._level_str(level),
                                                                                      t[0], t[1], t[2], t[3], t[4],
                                                                                      t[5], int(t[6]/1000),
                                                                                      caller,
                                                                                      message))
Esempio n. 7
0
def connect():
    wlan = network.WLAN(mode=network.WLAN.STA)
    wlan.connect('VM8707621', auth=(network.WLAN.WPA2, 'sm7zkSspWsmq'))
    while not wlan.isconnected():
        time.sleep_ms(50)
    print(wlan.ifconfig())
    rtc = RTC()
    rtc.ntp_sync("pool.ntp.org")
    while not rtc.synced():
        time.sleep_ms(50)
    print(rtc.now())
Esempio n. 8
0
    def logBoot(fileName):
        intRtc = RTC()
        if DataWriter.isFileCreated(fileName):
            openMode = 'a'
        else:
            openMode = 'x'

        with open(str(DataWriter.pathPrefix) + str(fileName),
                  openMode) as csvfile:
            row = ''
            args = intRtc.now()
            for x in args:
                if row != '':
                    row = row + ', ' + str(x)
                else:
                    row = str(x)
            csvfile.write(str(row) + '\n')
            csvfile.close()
Esempio n. 9
0
class DS3231:
    def __init__(self):
        self.ds3231 = I2C(0,
                          I2C.MASTER,
                          baudrate=100000,
                          pins=('GP15', 'GP10'))
        self.rtc = RTC()

    def loadTime(self):
        if DS3231_I2C_ADDR in self.ds3231.scan():
            data = self.ds3231.readfrom_mem(DS3231_I2C_ADDR, 0, 7)
            ss = bcd2dec(data[0] & 0b01111111)
            mm = bcd2dec(data[1] & 0b01111111)
            if data[2] & 0b01000000 > 0:
                hh = bcd2dec(data[2] & 0b00011111)
                if data[2] & 0b00100000 > 0:
                    hh += 12
            else:
                hh = bcd2dec(data[2] & 0b00111111)
            DD = bcd2dec(data[4] & 0b00111111)
            MM = bcd2dec(data[5] & 0b00011111)
            YY = bcd2dec(data[6])
            if data[5] & 0b10000000 > 0:
                YY = YY + 2000
            else:
                YY = YY + 1900
            self.rtc.init((YY, MM, DD, hh, mm, ss))
        else:
            print("DS3231 not found on I2C bus at %d" % DS3231_I2C_ADDR)

    def saveTime(self):
        (YY, MM, DD, hh, mm, ss, micro, tz) = self.rtc.now()
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 0, dec2bcd(ss))
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 1, dec2bcd(mm))
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 2, dec2bcd(hh))
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 4, dec2bcd(DD))
        if YY >= 2000:
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 5,
                                    dec2bcd(MM) | 0b10000000)
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 6, dec2bcd(YY - 2000))
        else:
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 5, dec2bcd(MM))
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 6, dec2bcd(YY - 1900))
Esempio n. 10
0
class DS3231:
    def __init__(self):
        self.ds3231 = I2C(0, I2C.MASTER, baudrate=100000, pins=('GP15', 'GP10'))
        self.rtc = RTC()
        
    def loadTime(self):
        if DS3231_I2C_ADDR in self.ds3231.scan():
            data = self.ds3231.readfrom_mem(DS3231_I2C_ADDR, 0, 7)
            ss=bcd2dec(data[0] & 0b01111111)
            mm=bcd2dec(data[1] & 0b01111111)
            if data[2] & 0b01000000 > 0:
                hh=bcd2dec(data[2] & 0b00011111)
                if data[2] & 0b00100000 >0:
                    hh+=12
            else:
                hh=bcd2dec(data[2] & 0b00111111)
            DD=bcd2dec(data[4] & 0b00111111)
            MM=bcd2dec(data[5] & 0b00011111)
            YY=bcd2dec(data[6])
            if data[5] & 0b10000000 > 0:
                YY=YY+2000
            else:
                YY=YY+1900
            self.rtc.init((YY,MM,DD,hh,mm,ss))
        else:
            print("DS3231 not found on I2C bus at %d" % DS3231_I2C_ADDR)


    def saveTime(self):
        (YY,MM,DD,hh,mm,ss,micro,tz) = self.rtc.now()
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 0,dec2bcd(ss));
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 1,dec2bcd(mm));
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 2,dec2bcd(hh));
        self.ds3231.writeto_mem(DS3231_I2C_ADDR, 4,dec2bcd(DD));
        if YY >= 2000:
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 5,dec2bcd(MM) | 0b10000000);
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 6,dec2bcd(YY-2000));
        else:
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 5,dec2bcd(MM));
            self.ds3231.writeto_mem(DS3231_I2C_ADDR, 6,dec2bcd(YY-1900));
Esempio n. 11
0
#Get curent time from the internet
#Note : The Loboris firmware works different from standard Micropython
# reference : https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki/rtc
from machine import RTC
import time
# Timezone is found in second field, text before the coma, in https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/blob/master/MicroPython_BUILD/components/micropython/docs/zones.csv
timezone = 'CET-1CEST'
rtc = RTC()
#Set the system time and date, (in this case very roughly).
rtc.init((2018, 01, 01, 12, 12, 12))
#configure to sync the time every hour with a Network Time Protocol (NTP) server
rtc.ntp_sync(server="", tz=timezone, update_period=3600)

# I may take some time for the ntp server to reply, so we need to wait
# Wait 5 sec or until time is synched ?
tmo = 50
while not rtc.synced():
    utime.sleep_ms(100)
    tmo -= 1
    if tmo == 0:
        break
#get the current,synchonized, time
rtc.now()
Esempio n. 12
0
#Read the button, if pressed then not in deepsleep mode and connected to your wifi (to avoid many problem to update your code)
bouton = Pin('G4', mode=Pin.IN, pull=Pin.PULL_UP)
if bouton() == 0 or True:  #TODO
    pycom.rgbled(0xff9900)  #orange
    from network import WLAN
    wlan = WLAN(mode=WLAN.STA)
    nets = wlan.scan()
    for net in nets:
        if net.ssid == 'TP-LINK_2.4GHz':
            print('SSID present.')
            wlan.connect(net.ssid,
                         auth=(net.sec, 'werbrauchtschoninternet'),
                         timeout=5000)
            while not wlan.isconnected():
                machine.idle()
            print('Connetion WLAN/WiFi OK!')

            print("Sync time.")
            rtc.ntp_sync("pool.ntp.org")
            while not rtc.synced():
                print("Wait to be in sync")
                time.sleep(10)
            print("RTC is in sync. ", rtc.now())
            # machine.main('main2.py')
            # machine.main('main.py')
            break
else:
    pycom.rgbled(0x7f0000)
    # machine.main('main.py')
machine.main('main.py')
Esempio n. 13
0
def getTemperature():
	global ADC_PIN_TMP36
	global T_MAX_MV
	global V_TO_MV
	global ADC_MAX_VAL
	global PRECISION_SCALE
	global OFFSET_MV
	global SCALE_FACTOR

	adc_tmp36 = ADC(0)
	apin_tmp36 = adc_tmp36.channel(pin=ADC_PIN_TMP36)
	rawTemp = 0
	for x in range(0, 100):
		adc_value = apin_tmp36.value()
		# read value (0~1024) then converted in mV then scaled to get more precision
		tMV = adc_value * (T_MAX_MV /  ADC_MAX_VAL)* PRECISION_SCALE
		# convert th mV received to temperature
		rawTemp += (tMV - OFFSET_MV) / 10

	return (rawTemp/100)

rtc = RTC()
rtc.ntp_sync('fr.pool.ntp.org')
sendData.connectLocalBox()

while 1==1:
	data = '{"temperature": %s, "timestamp": "%s", "battery" : %s}' % (getTemperature(),rtc.now(), readBatteryVoltage.readBatteryLevel())
	sendData.sendData(host='http://192.168.1.15', port=1338, data=data)
	time.sleep(300)
Esempio n. 14
0
    bt.start_scan(-1)

while True:
    try:
        adv = bt.get_adv()
        if adv:
            data = str(adv.data, "utf-8")
            data = str(data.split("#")[1][:8], "utf-8")
            data = ubinascii.a2b_base64(data)
            temperature = extractTemperature(data)
            humidity = extractHumidity(data)
            pressure = extractPressure(data)
            id = str(ubinascii.hexlify(adv.mac), "utf-8")

            content = '{"temperature": %s, "humidity": %s, "pressure" : %s, "mac": %s, "timestamp": "%s"}' % (
                temperature, humidity, pressure, id, rtc.now())
            print(content)
            sendData.send(host='http://192.168.1.15', port=1338, data=content)
            pycom.rgbled(0x007f00)  # green
            time.sleep(0.1)
            pycom.rgbled(0)
            try:
                bt.stop_scan()
            except:
                print("Error stopping...")
            time.sleep(60)
            try:
                bt.start_scan(-1)
            except:
                bt.stop_scan()
                bt.start_scan(-1)
Esempio n. 15
0
OFFSET_local=c.OFFSET_local                                         #paramètres de mesure de la température : à régler pour chaque Lopy

#Init variables locales
temperature_distant=0
temperature_local=0
poids_en_grammes=0
poids_en_gr_distant_total=0
poids_en_gr_local_total=0
lecture_capteur=[0]*9

liste=[0]*24                                                                    # liste des valeurs HX711 déclarées "fausses"
for i in range (24):
    liste[i]=2**i-1
    
#####################################################################################################################
print ('configuration:', configuration,  'debug:',  debug, 'mise en sommeil: ', wake,'date: ',   rtc.now(), 'premier_capteur_TX', c.premier_capteur, 'nombre_capteurs_TX', c.nombre_capteurs, 'premier_capteur_RX', c.premier_capteur_rx, 'nombre_capteurs_RX', c.nombre_capteurs_rx)

if configuration== 1: # ON VA écouter le TX et lire le RX, il y a  nombre_capteurs_rx capteurs sur le RX; il y a nombre_capteurs capteurs sur le TX;   
#trame enregistrée=label+delimiteur+str(numero_trame)+delimiteur+str(t)+delimiteur+w+{delimiteur+str(lecture_capteur[i])}*nb_capteurs+delimiteur+time_stamp+delimiteur+"\n"        
    lora = LoRa(mode=LoRa.LORA, frequency=c.LORA_FREQUENCY)
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    s.setblocking(False)
    while True:   
        trame_ch=s.recv(128)     
        pycom.rgbled(c.vert_pale)             
        time.sleep(2)         
        if trame_ch:      
            pycom.rgbled(c.rouge_pale)  
            print( "trame : ", trame_ch)
            time.sleep(2)         
            trame = trame_ch.decode('utf-8')                      #sinon pbs compatibilité avec binaire?
Esempio n. 16
0
class SenseLink:
    """
    Class object that receives optional pin arguments for the SDA-pin (Serial Data), the SCL-pin (Serial Clock) and the
    pin for the photometry module. The defaults are SDA = Pin3, SCL = Pin4, Phot = Pin20 on the Pycom Extension Board v3.1.
    """
    def __init__(self,
                 sda="P3",
                 scl="P4",
                 als="P20",
                 ssid="",
                 pw="",
                 frequency=5,
                 debug=0,
                 feed_layer=None):
        self.feed_layer = feed_layer
        self.fid = self.feed_layer.get_sensor_feed_fid()
        self.cfid = self.feed_layer.get_control_feed_fid()
        self.rtc = RTC()
        self.debug = debug
        self.lastsent = 0
        self.switch = True
        self.wlan = WLAN(mode=WLAN.STA)
        self.connectWlan(ssid=ssid, pw=pw)
        self.subscribe_state = self.feed_layer.subscribe_control_feed(
            self.callback)
        self.frequency = frequency
        self.__debug("Sensor Feed ID is: " + str(self.fid))
        self.__debug("Control Feed ID is: " + str(self.cfid))
        try:
            self.bme280 = bme280.BME280(i2c=I2C(pins=(sda, scl)))
        except:
            self.__exitError(
                "BME280 not recognized. Please check the connections.",
                loop=True,
                col=1)
        self.l_pin = ADC().channel(pin=als)

    def getFid(self):
        return self.fid

    def getCfid(self):
        return self.cfid

    def switchState(self):
        return self.switch

    def callback(self, event):
        self.__debug("Event received: {}".format(event))
        self.setFrequency(int(event))

    def setFrequency(self, val):
        self.__debug("Frequency changed to {}".format(val))
        self.frequency = val

    def getFrequency(self):
        return self.frequency

    def createEvent(self):
        self.vals = self.__getValues()
        event = "['{}', '{:.2f}', '{:.2f}', '{:.2f}', '{:.2f}']".format(
            self.vals[0], self.vals[1], self.vals[2], self.vals[3],
            self.vals[4])
        self.__debug("Creating event: " + event)
        return event

    def connectWlan(self, ssid, pw, timeout=5):
        self.wlan.connect(ssid=ssid, auth=(WLAN.WPA2, pw))
        counter = 0
        self.__debug("Connecting to WLAN", newline=False)
        while not self.wlan.isconnected():
            counter = counter + 1
            if (counter == timeout):
                self.__exitError("Unable to connect (timed out).",
                                 loop=True,
                                 col=0)
                return
            time.sleep(1)
            self.__debug(".", newline=False)
        if self.wlan.isconnected():
            self.__debug(" Connected! ", newline=False)
        counter = 0
        self.rtc.ntp_sync("0.ch.pool.ntp.org")
        self.__debug("Connecting to NTP server ", newline=False)
        while not self.rtc.synced():
            counter = counter + 1
            if (counter == timeout):
                self.__exitError("Unable to connect (timed out).",
                                 loop=True,
                                 col=0)
                return
            self.__debug(".", newline=False)
            time.sleep(1)
        self.__debug(" Completed!", newline=False)
        self.switch = False
        self.__debug("Connection established and time data received.")

    def __getTimeStamp(self,
                       offset_sec=0,
                       offset_min=0,
                       offset_hour=0,
                       offset_day=0,
                       offset_month=0,
                       offset_year=0):
        if self.wlan.isconnected():
            self.rtc.ntp_sync("0.ch.pool.ntp.org")
            time = self.rtc.now()
            seconds = self.__zfill(str(time[5] + offset_sec), 2)
            minutes = self.__zfill(str(time[4] + offset_min), 2)
            hour = self.__zfill(time[3] + offset_hour, 2)
            day = self.__zfill(time[2] + offset_day, 2)
            month = self.__zfill(time[1] + offset_month, 2)
            year = time[0] - 2000 + offset_year
            return "{}/{}/{} {}:{}:{}".format(day, month, year, hour, minutes,
                                              seconds)
        else:
            return "notime"

    def __zfill(self, s, width):
        return '{:0>{w}}'.format(s, w=width)

    def updateInfo(self):
        while True:
            self.__debug(self.__getTimeStamp() +
                         " Switch state: {}".format(self.switch))
            self.currentpack = self.__getValues()
            time.sleep(1)

    def __getValues(self):
        try:
            t, p, h = self.bme280.values
            li = self.l_pin()
            return self.__getTimeStamp(offset_hour=2), t, p, h, li / 4095 * 100
        except:
            self.__exitError(
                "BME280 not recognized. Please check the connections.",
                loop=True)

    def __exitError(self, str, col, loop=False):
        print('\033[91m' + "Error: " + str + '\x1b[0m')
        pycom.heartbeat(False)
        if col == 0:
            pycom.rgbled(0x7f7f00)
        elif col == 1:
            pycom.rgbled(0x7f0000)
        if loop:
            while True:
                pass
        else:
            sys.exit()

    def __debug(self, str, newline=True):
        if newline:
            print('\033[93m' + "SenseLink | Debug: " + str + '\x1b[0m')
        else:
            print('\033[93m' + str + '\x1b[0m', end='')
Esempio n. 17
0
f.close()

print('LED on')
pycom.rgbled(0x7f0000)  # red
time.sleep(2)

wlan = WLAN(mode=WLAN.STA)
#wlan.ifconfig(config=(wifi_strings[3], wifi_strings[4], wifi_strings[5], wifi_strings[6]))  #Enable for static IP use
wlan.connect(wifi_strings[0], auth=(WLAN.WPA2, wifi_strings[2]), timeout=5000)
print(
    'Wi-Fi Connecting To :',
    wifi_strings[0],
)
while not wlan.isconnected():
    machine.idle()  #loop until connected

print('Connected')
pycom.rgbled(0x00007f)  # blue
time.sleep(2)

print('Requesting Time Sync')
rtc = RTC()
rtc.ntp_sync('129.250.35.251', 3600)
pycom.rgbled(0xffff00)  # yellow
time.sleep(2)
print("Current Time - " + str(rtc.now()))
print("IP Details - " + str(wlan.ifconfig()))

pycom.rgbled(0x007f00)  # green
time.sleep(2)
Esempio n. 18
0
class Monitor(object):

    def __init__(
        self,
        solar_topic, grid_topic, mqtt_broker, wifi_credentials,
        graph_interval_s=60, update_interval_ms=1000
    ):
        self._solar_topic = solar_topic
        self._grid_topic = grid_topic
        self._mqtt_broker = mqtt_broker
        self._wifi_credentials = wifi_credentials
        self._graph_interval = graph_interval_s
        self._update_interval = update_interval_ms
        self._graph_window = Monitor._shorten(self._graph_interval * 320)

        self._tft = None
        self._wlan = None
        self._mqtt = None
        self._neopixel = None

        self._battery = IP5306(I2C(scl=Pin(22), sda=Pin(21)))
        self._timer = Timer(0)
        self._rtc = RTC()
        self._button_a = ButtonA(callback=self._button_a_pressed)
        self._button_b = ButtonB(callback=self._button_b_pressed)
        self._button_c = ButtonC(callback=self._button_c_pressed)

        self._reboot = False
        self._backup = False
        self._solar = None
        self._usage = None
        self._grid = None
        self._importing = None
        self._prev_importing = None
        self._solar_avg_buffer = []
        self._grid_avg_buffer = []
        self._usage_buffer = []
        self._usage_buffer_max = 0
        self._usage_buffer_min = 0
        self._usage_buffer_avg = 0
        self._usage_buffer_stddev = 0
        self._usage_max_coords = [0, 0]
        self._calculate_buffer_stats('usage', 0)
        self._solar_buffer = []
        self._solar_buffer_max = 0
        self._solar_buffer_min = 0
        self._solar_buffer_avg = 0
        self._solar_buffer_stddev = 0
        self._solar_max_coords = [0, 0]
        self._calculate_buffer_stats('solar', 0)
        self._last_update = (0, 0, 0, 0, 0, 0)
        self._data_received = [False, False]
        self._buffer_updated = False
        self._realtime_updated = False
        self._last_value_added = None
        self._graph_max = 0
        self._solar_max = 0
        self._usage_max = 0
        self._menu_horizontal_pointer = 0
        self._menu_tick = 0
        self._menu_tick_divider = 0
        self._blank_menu = False
        self._save = False
        self._show_markers = True
        self._color = None
        self._ticks = {'M': 0,  # MQTT message
                       'D': 0,  # Data sample (solar + grid)
                       'R': 0,  # Remaining time for next graph update
                       'G': 0,  # Graph datapoint added
                       'B': 0,  # Button press
                       'E': 0}  # Exceptions
        self._tick_keys = ['M', 'D', 'G', 'B', 'R', 'E']
        self._last_exception = 'None'
        self._runtime_config_parameters = ['show_markers']
        self._last_logline = ''

        self._log('Initializing TFT...')
        self._tft = display.TFT()
        self._tft.init(self._tft.M5STACK, width=240, height=320, rst_pin=33, backl_pin=32, miso=19, mosi=23, clk=18, cs=14, dc=27, bgr=True, backl_on=1)
        self._tft.tft_writecmd(0x21)  # Invert colors
        self._tft.clear()
        self._tft.font(self._tft.FONT_Default, transparent=False)
        self._tft.text(0, 0, 'USAGE', self._tft.DARKGREY)
        self._tft.text(self._tft.CENTER, 0, 'IMPORTING', self._tft.DARKGREY)
        self._tft.text(self._tft.RIGHT, 0, 'SOLAR', self._tft.DARKGREY)
        self._tft.text(0, 14, 'Loading...', self._tft.DARKGREY)
        self._log('Initializing TFT... Done')

    def init(self):
        """ Init logic; connect to wifi, connect to MQTT and setup RTC/NTP """
        self._log('Connecting to wifi ({0})... '.format(self._wifi_credentials[0]), tft=True)
        self._wlan = network.WLAN(network.STA_IF)
        self._wlan.active(True)
        self._wlan.connect(*self._wifi_credentials)
        safety = 10
        while not self._wlan.isconnected() and safety > 0:
            # Wait for the wifi to connect, max 10s
            time.sleep(1)
            safety -= 1
        self._log('Connecting to wifi ({0})... {1}'.format(self._wifi_credentials[0], 'Done' if safety else 'Fail'))
        mac_address = ubinascii.hexlify(self._wlan.config('mac'), ':').decode()
        self._log('Connecting to MQTT...', tft=True)
        if self._mqtt is not None:
            self._mqtt.unsubscribe('emon/#')
        self._mqtt = network.mqtt('emon', self._mqtt_broker, user='******', password='******', clientid=mac_address, data_cb=self._process_data)
        self._mqtt.start()
        safety = 5
        while self._mqtt.status()[0] != 2 and safety > 0:
            # Wait for MQTT connection, max 5s
            time.sleep(1)
            safety -= 1
        self._mqtt.subscribe('emon/#')
        self._log('Connecting to MQTT... {0}'.format('Done' if safety else 'Fail'))
        self._log('Sync NTP...', tft=True)
        self._rtc.ntp_sync(server='be.pool.ntp.org', tz='CET-1CEST-2')
        safety = 5
        while not self._rtc.synced() and safety > 0:
            # Wait for NTP time sync, max 5s
            time.sleep(1)
            safety -= 1
        self._last_update = self._rtc.now()
        self._log('Sync NTP... {0}'.format('Done' if safety else 'Fail'))
        self._log('Initializing Neopixels...', tft=True)
        try:
            self._neopixel = Neopixel(Pin(15), 10, Neopixel.TYPE_RGB)
            self._neopixel.clear()
        except Exception:
            self._neopixel = None
        self._log('Initializing Neopixels... {0}'.format('Available' if self._neopixel is not None else 'Unavailable'))
        self._tft.text(0, 14, ' ' * 50, self._tft.DARKGREY)  # Clear the line

    def _process_data(self, message):
        """ Process MQTT message """
        try:
            topic = message[1]
            data = float(message[2])
            self._ticks['M'] += 1

            # Collect data samples from solar & grid
            if topic == self._solar_topic:
                self._solar = max(0.0, data)
                self._data_received[0] = True
            elif topic == self._grid_topic:
                self._grid = data
                self._data_received[1] = True

            if self._data_received[0] and self._data_received[1]:
                self._ticks['D'] += 1
                # Once the data has been received, calculate realtime usage
                self._usage = self._solar + self._grid

                self._last_update = self._rtc.now()
                self._realtime_updated = True  # Redraw realtime values
                self._data_received = [False, False]

                # Process data for the graph; collect solar & grids, and every x-pixel
                # average the data out and draw them on that pixel.
                now = time.time()
                rounded_now = int(now - now % self._graph_interval)
                if self._last_value_added is None:
                    self._last_value_added = rounded_now
                self._ticks['R'] = int(rounded_now + self._graph_interval - now)
                self._solar_avg_buffer.append(int(self._solar))
                self._grid_avg_buffer.append(int(self._grid))
                if self._last_value_added != rounded_now:
                    self._ticks['G'] += 1
                    solar, usage = self._read_avg_buffer(reset=True)
                    self._solar_buffer.append(solar)
                    self._solar_buffer = self._solar_buffer[-319:]  # Keep one pixel for moving avg
                    self._calculate_buffer_stats('solar', solar)
                    self._usage_buffer.append(usage)
                    self._usage_buffer = self._usage_buffer[-319:]  # Keep one pixel for moving avg
                    self._calculate_buffer_stats('usage', usage)
                    self._last_value_added = rounded_now
                    self._buffer_updated = True  # Redraw the complete graph
        except Exception as ex:
            self._last_exception = str(ex)
            self._ticks['E'] += 1
            self._log('Exception in process data: {0}'.format(ex))

    def _calculate_buffer_stats(self, buffer_type, single_value):
        buffer = getattr(self, '_{0}_buffer'.format(buffer_type))
        if len(buffer) == 0:
            return
        setattr(self, '_{0}_buffer_max'.format(buffer_type), single_value if len(buffer) == 1 else max(*buffer))
        setattr(self, '_{0}_buffer_min'.format(buffer_type), single_value if len(buffer) == 1 else min(*buffer))
        setattr(self, '_{0}_buffer_avg'.format(buffer_type), sum(buffer) / len(buffer))
        setattr(self, '_{0}_buffer_stddev'.format(buffer_type), Monitor._stddev(buffer))

    def _read_avg_buffer(self, reset):
        solar_avg_buffer_length = len(self._solar_avg_buffer)
        grid_avg_buffer_length = len(self._grid_avg_buffer)
        if solar_avg_buffer_length == 0 or grid_avg_buffer_length == 0:
            return 0, 0
        solar = int(sum(self._solar_avg_buffer) / solar_avg_buffer_length)
        grid = int(sum(self._grid_avg_buffer) / grid_avg_buffer_length)
        usage = solar + grid
        if reset:
            self._solar_avg_buffer = []
            self._grid_avg_buffer = []
        return solar, usage

    def load(self):
        self._log('Loading runtime configuration...', tft=True)
        if 'runtime_config.json' in os.listdir('/flash'):
            with open('/flash/runtime_config.json', 'r') as f:
                runtime_config = ujson.load(f)
            for key in self._runtime_config_parameters:
                if key in runtime_config:
                    setattr(self, '_{0}'.format(key), runtime_config[key])
        self._log('Loading runtime configuration... Done', tft=True)
        self._log('Restoring backup...', tft=True)
        if 'backup.json' in os.listdir('/flash'):
            with open('/flash/backup.json', 'r') as f:
                backup = ujson.load(f)
            self._usage_buffer = backup.get('usage_buffer', [])
            self._calculate_buffer_stats('usage', 0)
            self._solar_buffer = backup.get('solar_buffer', [])
            self._calculate_buffer_stats('solar', 0)
            os.remove('/flash/backup.json')
        self._log('Restoring backup... Done', tft=True)

    def run(self):
        """ Set timer """
        self._timer.init(period=self._update_interval, mode=Timer.PERIODIC, callback=self._tick)

    def _tick(self, timer):
        """ Do stuff at a regular interval """
        _ = timer
        self._draw()
        try:
            # At every tick, make sure wifi is still connected
            if not self._wlan.isconnected():
                self.init()
        except Exception as ex:
            self._last_exception = str(ex)
            self._ticks['E'] += 1
            self._log('Exception in watchdog: {0}'.format(ex))
        if self._reboot:
            self._take_backup()
            self._save_runtime_config()
            machine.reset()
        if self._backup:
            self._take_backup()
            self._save_runtime_config()
            self._backup = False
        if self._save:
            self._save_runtime_config()
            self._save = False

    def _save_runtime_config(self):
        data = {}
        for key in self._runtime_config_parameters:
            data[key] = getattr(self, '_{0}'.format(key))
        with open('/flash/runtime_config.json', 'w') as runtime_config_file:
            runtime_config_file.write(ujson.dumps(data))

    def _take_backup(self):
        with open('/flash/backup.json', 'w') as backup_file:
            backup_file.write(ujson.dumps({'usage_buffer': self._usage_buffer,
                                           'solar_buffer': self._solar_buffer}))

    def _draw(self):
        """ Update display """
        try:
            self._draw_realtime()
        except Exception as ex:
            self._last_exception = str(ex)
            self._ticks['E'] += 1
            self._log('Exception in draw realtime: {0}'.format(ex))
        try:
            self._draw_graph()
        except Exception as ex:
            self._last_exception = str(ex)
            self._ticks['E'] += 1
            self._log('Exception in draw graph: {0}'.format(ex))
        try:
            self._draw_menu()
        except Exception as ex:
            self._last_exception = str(ex)
            self._ticks['E'] += 1
            self._log('Exception in draw menu: {0}'.format(ex))
        try:
            self._draw_rgb()
        except Exception as ex:
            self._last_exception = str(ex)
            self._ticks['E'] += 1
            self._log('Exception in draw rgb: {0}'.format(ex))

    def _draw_rgb(self):
        """ Uses the neopixel leds (if available) to indicate how "good" our power consumption is. """
        if self._neopixel is None:
            return
        if len(self._solar_buffer) == 0 or self._usage is None:
            self._neopixel.clear()
            return

        high_usage = self._usage > self._usage_buffer_avg + (self._usage_buffer_stddev * 2)
        if self._grid < 0:
            # Feeding back to the grid
            score = 0
            if self._grid < -500:
                score += 1
            if self._grid < -1000:
                score += 1
            if high_usage:
                score -= 1
            colors = [Neopixel.GREEN, Neopixel.LIME, Neopixel.YELLOW]
            color = colors[max(0, score)]
        else:
            score = 0
            if high_usage:
                score += 1
            if self._solar == 0:
                score += 1
            colors = [Neopixel.BLUE, Neopixel.PURPLE, Neopixel.RED]
            color = colors[max(0, score)]
        if self._color != color:
            self._neopixel.set(0, color, num=10)
            self._color = color

    def _draw_realtime(self):
        """ Realtime part; current usage, importing/exporting and solar """
        if not self._realtime_updated:
            return

        self._tft.text(self._tft.RIGHT, 14, '          {0:.2f}W'.format(self._solar), self._tft.YELLOW)
        self._tft.text(0, 14, '{0:.2f}W          '.format(self._usage), self._tft.BLUE)
        self._importing = self._grid > 0
        if self._prev_importing != self._importing:
            if self._importing:
                self._tft.text(self._tft.CENTER, 0, '  IMPORTING  ', self._tft.DARKGREY)
            else:
                self._tft.text(self._tft.CENTER, 0, '  EXPORTING  ', self._tft.DARKGREY)
        if self._importing:
            self._tft.text(self._tft.CENTER, 14, '  {0:.2f}W  '.format(abs(self._grid)), self._tft.RED)
        else:
            self._tft.text(self._tft.CENTER, 14, '  {0:.2f}W  '.format(abs(self._grid)), self._tft.GREEN)
        self._prev_importing = self._importing
        self._realtime_updated = False

    def _draw_graph(self):
        """ Draw the graph part """
        solar_moving_avg, usage_moving_avg = self._read_avg_buffer(reset=False)
        solar_max = max(self._solar_buffer_max, solar_moving_avg)
        usage_max = max(self._usage_buffer_max, usage_moving_avg)
        max_value = float(max(solar_max, usage_max))
        if max_value != self._graph_max:
            self._graph_max = max_value
            self._buffer_updated = True
        if solar_max != self._solar_max:
            self._solar_max = solar_max
            self._buffer_updated = True
        if usage_max != self._usage_max:
            self._usage_max = usage_max
            self._buffer_updated = True
        ratio = 1 if max_value == 0 else (180.0 / max_value)
        show_markers = self._show_markers and max_value > 0
        buffer_size = len(self._usage_buffer)

        avg_marker = False
        usage_max_coords = self._usage_max_coords
        solar_max_coords = self._solar_max_coords
        if self._buffer_updated:
            for index, usage in enumerate(self._usage_buffer):
                solar = self._solar_buffer[index]
                usage_y, solar_y = self._draw_graph_line(index, solar, usage, ratio)
                if usage == usage_max:
                    usage_max_coords = [index, usage_y]
                if solar == solar_max:
                    solar_max_coords = [index, solar_y]
        usage_y, solar_y = self._draw_graph_line(buffer_size, solar_moving_avg, usage_moving_avg, ratio)
        if usage_moving_avg == usage_max:
            avg_marker = True
            usage_max_coords = [buffer_size, usage_y]
        if solar_moving_avg == solar_max:
            avg_marker = True
            solar_max_coords = [buffer_size, solar_y]

        max_coords_changed = self._usage_max_coords != usage_max_coords or self._solar_max_coords != solar_max_coords
        if self._buffer_updated and max_coords_changed:
            self._tft.rect(buffer_size + 1, 40, 320, 220, self._tft.BLACK, self._tft.BLACK)
        if show_markers:
            self._draw_marker('{0:.0f}W'.format(solar_max), solar_max_coords, not avg_marker)
            self._draw_marker('{0:.0f}W'.format(usage_max), usage_max_coords, not avg_marker)
        self._usage_max_coords = usage_max_coords
        self._solar_max_coords = solar_max_coords
        self._buffer_updated = False

    def _draw_marker(self, text, coords, transparent):
        x, y = coords
        if x > 160:
            text_x = x - self._tft.textWidth(text) - 10
            line_start_x = x - 2
            line_end_x = x - 8
        else:
            text_x = x + 10
            line_start_x = x + 2
            line_end_x = text_x - 2
        if y > 120:
            text_y = y - 22
        else:
            text_y = y + 10
        self._tft.font(self._tft.FONT_Default, transparent=transparent)
        self._tft.text(text_x, text_y, text, self._tft.DARKGREY)
        self._tft.line(line_start_x, y, line_end_x, text_y + 6, self._tft.DARKGREY)
        self._tft.font(self._tft.FONT_Default, transparent=False)

    def _draw_graph_line(self, index, solar, usage, ratio):
        usage_height = int(usage * ratio)
        solar_height = int(solar * ratio)
        usage_y = 220 - usage_height
        solar_y = 220 - solar_height
        max_height = max(usage_height, solar_height)
        self._tft.line(index, 40, index, 220 - max_height, self._tft.BLACK)
        if usage_height > solar_height:
            self._tft.line(index, usage_y, index, solar_y, self._tft.BLUE)
            if solar_height > 0:
                self._tft.line(index, solar_y, index, 220, self._tft.DARKCYAN)
        else:
            self._tft.line(index, solar_y, index, usage_y, self._tft.YELLOW)
            if usage_height > 0:
                self._tft.line(index, usage_y, index, 220, self._tft.DARKCYAN)
        return usage_y, solar_y

    def _draw_menu(self):
        if self._blank_menu:
            self._tft.rect(0, 221, 320, 240, self._tft.BLACK, self._tft.BLACK)
            self._blank_menu = False
        if self._menu_horizontal_pointer == 0:
            data = 'Updated:  {0:04d}/{1:02d}/{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(*self._last_update[:6])
        elif self._menu_horizontal_pointer == 1:
            data = 'Battery: {0}%'.format(self._battery.level)
        elif self._menu_horizontal_pointer == 2:
            data = 'Graph: {0} {1}, max {2:.2f}W'.format(len(self._usage_buffer), self._graph_window, self._graph_max)
        elif self._menu_horizontal_pointer in [3, 4]:
            data_type = 'solar' if self._menu_horizontal_pointer == 3 else 'usage'
            solar, usage = self._read_avg_buffer(reset=False)
            if self._menu_tick == 0:
                value = min(
                    getattr(self, '_{0}_buffer_min'.format(data_type)),
                    solar if data_type == 'solar' else usage,
                    self._solar if data_type == 'solar' else self._usage
                )
                info = 'min'
            elif self._menu_tick == 1:
                value = getattr(self, '_{0}_buffer_avg'.format(data_type))
                info = 'avg'
            elif self._menu_tick == 2:
                value = getattr(self, '_{0}_buffer_avg'.format(data_type)) + (getattr(self, '_{0}_buffer_stddev'.format(data_type)) * 2)
                info = 'high'
            else:
                value = max(
                    getattr(self, '_{0}_buffer_max'.format(data_type)),
                    solar if data_type == 'solar' else usage,
                    self._solar if data_type == 'solar' else self._usage
                )
                info = 'max'
            data = '{0}{1} stats: {2:.2f}W {3}'.format(data_type[0].upper(), data_type[1:], value, info)
        elif self._menu_horizontal_pointer == 5:
            data = 'Time: {0}'.format(time.time())
        elif self._menu_horizontal_pointer == 6:
            data = 'Exception: {0}'.format(self._last_exception[:20])
        elif self._menu_horizontal_pointer == 7:
            data = 'Press B to reboot'
        elif self._menu_horizontal_pointer == 8:
            data = 'Press B to take a backup'
        elif self._menu_horizontal_pointer == 9:
            data = 'Press B to {0} markers'.format('hide' if self._show_markers else 'show')
        elif self._menu_horizontal_pointer == 10:
            log_entry = self._last_logline[:26]
            if len(log_entry) < 26:
                log_entry += ' ' * (26 - len(log_entry))
            data = 'Log: {0}'.format(log_entry)
        else:
            data = 'Ticks: {0}'.format(', '.join('{0}'.format(self._ticks[key]) for key in self._tick_keys))
        self._tft.text(0, self._tft.BOTTOM, '<', self._tft.DARKGREY)
        self._tft.text(self._tft.RIGHT, self._tft.BOTTOM, '>', self._tft.DARKGREY)
        if len(data) < 32:
            padding = int(float(32 - len(data) + 1) / 2)
            data = '{0}{1}{2}'.format(' ' * padding, data, ' ' * padding)
        self._tft.text(self._tft.CENTER, self._tft.BOTTOM, data, self._tft.DARKGREY)
        self._menu_tick_divider += 1
        if self._menu_tick_divider == 3:  # Increase menu tick every X seconds
            self._menu_tick += 1
            if self._menu_tick == 4:
                self._menu_tick = 0
            self._menu_tick_divider = 0

    def _button_a_pressed(self, pin, pressed):
        _ = pin
        if pressed:
            self._ticks['B'] += 1
            self._menu_horizontal_pointer -= 1
            if self._menu_horizontal_pointer < 0:
                self._menu_horizontal_pointer = 11
            self._blank_menu = True

    def _button_b_pressed(self, pin, pressed):
        _ = pin
        if pressed:
            if self._menu_horizontal_pointer == 7:
                self._reboot = True
            elif self._menu_horizontal_pointer == 8:
                self._backup = True
            elif self._menu_horizontal_pointer == 9:
                self._show_markers = not self._show_markers
                self._save = True

    def _button_c_pressed(self, pin, pressed):
        _ = pin
        if pressed:
            self._ticks['B'] += 1
            self._menu_horizontal_pointer += 1
            if self._menu_horizontal_pointer > 11:
                self._menu_horizontal_pointer = 0
            self._blank_menu = True

    @staticmethod
    def _stddev(entries):
        """ returns the standard deviation of lst """
        avg = sum(entries) / len(entries)
        variance = sum([(e - avg) ** 2 for e in entries]) / len(entries)
        return sqrt(variance)

    @staticmethod
    def _shorten(seconds):
        """ Converts seconds to a `xh ym ys` notation """
        parts = []
        seconds_hour = 60 * 60
        seconds_minute = 60
        if seconds >= seconds_hour:
            hours = int((seconds - seconds % seconds_hour) / seconds_hour)
            seconds = seconds - (hours * seconds_hour)
            parts.append('{0}h'.format(hours))
        if seconds >= seconds_minute:
            minutes = int((seconds - seconds % seconds_minute) / seconds_minute)
            seconds = seconds - (minutes * seconds_minute)
            parts.append('{0}m'.format(minutes))
        if seconds > 0:
            parts.append('{0}s'.format(seconds))
        return ' '.join(parts)

    def _log(self, message, tft=False):
        """ Logs a message to the console and (optionally) to the display """
        print(message)
        self._last_logline = message
        if tft:
            self._tft.text(0, 14, '{0}{1}'.format(message, ' ' * 50), self._tft.DARKGREY)
Esempio n. 19
0
import watermark # module needed in library for reading Watermark sensors (written by Jan D)
import time, ubinascii
from onewire import OneWire, DS18X20
from machine import RTC
from network import LoRa
import socket
import binascii
import struct
import ustruct
import config

pycom.heartbeat(False) # stop the heartbeat

# Set up the Real Time Clock (RTC)
rtc = RTC()
print(rtc.now()) # This will print date and time if it was set before going
# to deepsleep.  The RTC keeps running in deepsleep.

#WAKE UP
print("wake reason (wake_reason, gpio_list):",machine.wake_reason())
'''   PWRON_WAKE -- 0
      PIN_WAKE -- 1
      RTC_WAKE -- 2
      ULP_WAKE -- 3
 '''

for cycle in range(1):
    # initialize LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
Esempio n. 20
0
# Send data to Sigfox. LED orange
time.sleep_ms(1000)
payload_data = convert_data_to_bytes_payload(data_type=data_type,
                                             device_id=device_id,
                                             deployment=deployment_seq,
                                             lat=data_gps['latitude'],
                                             lon=data_gps['longitude'],
                                             alt=data_gps['altitude'],
                                             hdop=data_gps['hdop'])
data_sent = send_data_Sigfox(bytes(payload_data))
blink_led(1, 1000, led_orange)

# Save data to SD. LED blue
time.sleep_ms(1000)
save_header()
save_data(device_id=device_id,
          deployment=deployment_seq,
          datetime=rtc.now(),
          lat=data_gps['latitude'],
          lon=data_gps['longitude'],
          alt=data_gps['altitude'],
          hdop=data_gps['hdop'],
          volt=volt,
          data_sent=data_sent)
blink_led(1, 1000, led_blue)

# Enter to deep sleep. LED red
time.sleep_ms(1000)
blink_led(1, 1000, led_red)
deep_sleep(time_to_deep_sleep)
Esempio n. 21
0
class HttpNotifier():
    def connection_timer_handler(self, alarm):
        if not self._wlan.isconnected():
            print('failed to connect to {}, restarting...'.format(wifi_config['ssid']))
            reset()

    def sync_timer_handler(self, alarm):
        if not self._rtc.synced():
            print('failed to sync time with ntp, restarting...')
            reset()

    def __init__(self, thng_id, api_key):
        self._thng_id = thng_id
        self._http_headers = {'Content-Type': 'application/json', 'Authorization': api_key}
        self._rtc = RTC()

        self._wlan = WLAN(mode=WLAN.STA)
        nets = self._wlan.scan()

        print('WLAN: scanned networks: {}'.format([net.ssid for net in nets]))

        for net in nets:
            if net.ssid == wifi_config['ssid']:
                print('WLAN: connecting to {}...'.format(net.ssid))
                self._wlan.connect(wifi_config['ssid'], auth=(
                    net.sec, wifi_config['passphrase']), timeout=30000)
                Timer.Alarm(self.connection_timer_handler, 35, periodic=False)
                while not self._wlan.isconnected():
                    idle()  # save power while waiting
                print('WLAN: connection to {} succeeded!'.format(wifi_config['ssid']))
                print('ifconfig: {}'.format(self._wlan.ifconfig()))
                self._send_props([{'key': 'in_use', 'value': False}])

                Timer.Alarm(self.sync_timer_handler, 30, periodic=False)
                while not self._rtc.synced():
                    self._rtc.ntp_sync('pool.ntp.org', update_period=3600)
                    time.sleep(1)
                print("time synced: {}".format(self._rtc.now()))

        # seems like we are still not connected,
        # setup wifi network does not exist ???
        if not self._wlan.isconnected():
            print('failed to connect or specified network does not exist')
            time.sleep(20)
            reset()
            # provision.enter_provisioning_mode()

    def _send(self, method, url, json):
        print('REQUEST: {}: {}'.format(method, json))
        try:
            resp = requests.request(method=method,
                                    url=url,
                                    json=json,
                                    headers=self._http_headers)
        except OSError as e:
            print('RESPONSE: failed to perform request: {}'.format(e))
            if not self._wlan.isconnected():
                print('wifi connection lost, restarting...')
                time.sleep(3)
                reset()
        else:
            print('RESPONSE: {}...'.format(str(resp.json())[:100]))
            gc_collect()

    def _send_props(self, data):
        self._send(method='PUT',
                   url='https://api.evrythng.com/thngs/{}/properties'.format(self._thng_id),
                   json=data)

    def _send_actions(self, data):
        for action in data:
            self._send(method='POST',
                       url='https://api.evrythng.com/thngs/{}/actions/all'.format(self._thng_id),
                       json=action)

    def handle_notifications(self, notifications):
        properties = []
        actions = []
        for n in notifications:
            if n.type == NotificationQueue.VIBRATION_STARTED:
                properties.append({'key': 'in_use', 'value': True, 'timestamp': n.timestamp})
                actions.append({'type': '_appliance_started', 'timestamp': n.timestamp})

            elif n.type == NotificationQueue.VIBRATION_STOPPED:
                properties.extend([{'key': 'in_use', 'value': False, 'timestamp': n.timestamp},
                                   {'key': 'last_use', 'value': n.data, 'timestamp': n.timestamp}])
                actions.append({'type': '_appliance_stopped', 'timestamp': n.timestamp})

            elif n.type == NotificationQueue.UPTIME:
                properties.append({'key': 'uptime', 'value': n.data, 'timestamp': n.timestamp})

            elif n.type == NotificationQueue.AMBIENT:
                properties.extend([
                    {'key': 'temperature', 'value': n.data[0], 'timestamp': n.timestamp},
                    {'key': 'humidity', 'value': n.data[1], 'timestamp': n.timestamp},
                    {'key': 'pressure', 'value': n.data[2], 'timestamp': n.timestamp},
                    {'key': 'battery_voltage', 'value': n.data[3], 'timestamp': n.timestamp}
                ])

            elif n.type == NotificationQueue.VERSION:
                properties.append({'key': 'version', 'value': n.data, 'timestamp': n.timestamp})

            elif n.type == NotificationQueue.MAGNITUDE:
                if not len(n.data):
                    return
                properties.append({'key': 'magnitude', 'value': n.data, 'timestamp': n.timestamp})

            else:
                print('unsupported event {}'.format(n.type))

        if actions:
            self._send_actions(actions)
        if properties:
            self._send_props(properties)
Esempio n. 22
0
def print_debug_local(level, msg):
    """
    Print log messages.

    log messages will be stored in the device so
    the user can access that using FTP or Flash OTA.
    """
    if DEBUG is not None and level <= DEBUG:
        print_debug(0, 'adding local log')
        rtc = RTC()
        if not rtc.synced():
            rtc.ntp_sync("pool.ntp.org")
        while not rtc.synced():
            pass
        current_year, current_month, current_day, current_hour, current_minute, current_second, current_microsecond, current_tzinfo = rtc.now() # noqa
        msg = '\n {}-{}-{} {}:{}:{} (GMT+{}) >>>  {}'.format(
            current_day,
            current_month,
            current_year,
            current_hour,
            current_minute,
            current_second,
            timezone(),
            msg
        )
        try:
            fsize = os.stat('logs.log')
            if fsize.st_size > 1000000:
                # logs are bigger than 1 MB
                os.remove("logs.log")
        except Exception:
            pass

        log_file = open('logs.log', 'a+')
        log_file.write(msg)
        log_file.close()
Esempio n. 23
0
class TerkinDevice:
    """
    Singleton object for enabling different device-related subsystems
    and providing lowlevel routines for sleep/resume functionality.
    """
    def __init__(self, application_info: ApplicationInfo):

        self.application_info = application_info
        self.platform_info = application_info.platform_info

        self.name = application_info.name
        self.version = application_info.version
        self.settings = application_info.settings

        self.status = DeviceStatus()
        self.watchdog = Watchdog(device=self, settings=self.settings)

        # Conditionally enable terminal on UART0. Default: False.
        #try:
        #    self.terminal = Terminal(self.settings)
        #    self.terminal.start()
        #except Exception as ex:
        #    log.exc(ex, 'Enabling Terminal failed')

        self.device_id = get_device_id()

        self.networking = None
        self.telemetry = None

        self.rtc = None

    def start_networking(self):
        """ 
        Start all configured networking devices.
        """
        log.info('Starting networking')

        from terkin.network import NetworkManager, WiFiException

        self.networking = NetworkManager(device=self, settings=self.settings)

        if self.settings.get('networking.wifi.enabled'):
            # Start WiFi.
            try:
                self.networking.start_wifi()

            except Exception as ex:
                log.exc(ex, 'Starting WiFi networking failed')
                self.status.networking = False
                return

            # Wait for network stack to come up.
            try:
                self.networking.wait_for_ip_stack(timeout=5)
                self.status.networking = True
            except Exception as ex:
                log.exc(ex, 'IP stack not available')
                self.status.networking = False

        else:
            log.info("[WiFi] Interface not enabled in settings.")

        try:
            self.networking.start_services()
        except Exception as ex:
            log.exc(ex, 'Starting network services failed')

        # Initialize LoRa device.
        platform_info = self.application_info.platform_info
        is_pycom_lora = platform_info.device_name in ['LoPy', 'LoPy4', 'FiPy']
        is_dragino = platform_info.vendor == platform_info.MICROPYTHON.RaspberryPi
        if self.settings.get('networking.lora.enabled'):
            if is_pycom_lora or is_dragino:
                if self.settings.get('networking.lora.antenna_attached'):
                    try:
                        self.networking.start_lora()
                        self.status.networking = True
                    except Exception as ex:
                        log.exc(ex, 'Unable to start LoRa subsystem')
                        self.status.networking = False
                else:
                    log.info(
                        "[LoRa] Disabling LoRa interface as no antenna has been attached. "
                        "ATTENTION: Running LoRa without antenna will wreck your device."
                    )
            else:
                log.error("[LoRa] This is not a LoRa capable device.")
        else:
            log.info("[LoRa] Interface not enabled in settings.")

        # Initialize LTE modem.
        if self.settings.get('networking.lte.enabled'):
            try:
                self.networking.start_lte()
                self.status.networking = True
            except Exception as ex:
                log.exc(ex, 'Unable to start LTE modem')
                self.status.networking = False
        else:
            log.info("[LTE]  Interface not enabled in settings.")

        # Initialize GPRS modem.
        if self.settings.get('networking.gprs.enabled'):
            try:
                self.networking.start_gprs()
                self.status.networking = True
            except Exception as ex:
                log.exc(ex, 'Unable to start GPRS modem')
                self.status.networking = False
        else:
            log.info("[GPRS] Interface not enabled in settings.")

        # Inform about networking status.
        #self.networking.print_status()

    def start_rtc(self):
        """
        The RTC is used to keep track of the date and time.
        Syncs RTC with a NTP server.
        """
        # https://docs.pycom.io/firmwareapi/pycom/machine/rtc.html
        # https://medium.com/@chrismisztur/pycom-uasyncio-installation-94931fc71283
        import time
        from machine import RTC
        self.rtc = RTC()
        # TODO: Use values from configuration settings here.
        self.rtc.ntp_sync("pool.ntp.org", 360)
        while not self.rtc.synced():
            time.sleep_ms(50)
        log.info('RTC: %s', self.rtc.now())

    def run_gc(self):
        """
        Curate the garbage collector.
        https://docs.pycom.io/firmwareapi/micropython/gc.html

        For a "quick fix", issue the following periodically.
        https://community.hiveeyes.org/t/timing-things-on-micropython-for-esp32/2329/9

        """
        import gc
        log.info('Start curating the garbage collector')
        gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
        log.info('Collecting garbage')
        gc.collect()
        #log.info('Curating the garbage collector finished')
        log.info('Curating the garbage collector finished. Free memory: %s',
                 gc.mem_free())

    def configure_rgb_led(self):
        """https://docs.pycom.io/tutorials/all/rgbled.html"""
        if self.platform_info.vendor == self.platform_info.MICROPYTHON.Pycom:
            import pycom
            # Enable or disable heartbeat.
            rgb_led_heartbeat = self.settings.get('main.rgb_led.heartbeat',
                                                  True)
            terkin_blink_pattern = self.settings.get('main.rgb_led.terkin',
                                                     False)
            if terkin_blink_pattern:
                rgb_led_heartbeat = False
            pycom.heartbeat(rgb_led_heartbeat)
            pycom.heartbeat_on_boot(rgb_led_heartbeat)

    def blink_led(self, color, count=1):
        """

        :param color: 
        :param count:  (Default value = 1)

        """
        if self.platform_info.vendor == self.platform_info.MICROPYTHON.Pycom:
            import pycom
            terkin_blink_pattern = self.settings.get('main.rgb_led.terkin',
                                                     False)
            if terkin_blink_pattern:
                for _ in range(count):
                    pycom.rgbled(color)
                    time.sleep(0.15)
                    pycom.rgbled(0x000000)
                    time.sleep(0.10)

    def start_telemetry(self):
        """ """
        log.info('Starting telemetry')

        self.telemetry = TelemetryManager()

        # Read all designated telemetry targets from configuration settings.
        telemetry_targets = self.settings.get('telemetry.targets', [])

        # Compute list of all _enabled_ telemetry targets.
        telemetry_candidates = []
        for telemetry_target in telemetry_targets:
            if telemetry_target.get('enabled', False):
                telemetry_candidates.append(telemetry_target)

        # Create adapter objects for each enabled telemetry target.
        for telemetry_target in telemetry_candidates:
            try:
                self.create_telemetry_adapter(telemetry_target)
                self.watchdog.feed()

            except Exception as ex:
                log.exc(ex, 'Creating telemetry adapter failed for target: %s',
                        telemetry_target)

    def create_telemetry_adapter(self, telemetry_target):
        """

        :param telemetry_target: 

        """
        # Create adapter object.
        telemetry_adapter = TelemetryAdapter(device=self,
                                             target=telemetry_target)

        # Setup telemetry adapter.
        telemetry_adapter.setup()

        self.telemetry.add_adapter(telemetry_adapter)

    def enable_serial(self):
        """ """
        # Disable these two lines if you don't want serial access.
        # The Pycom forum tells us that this is already incorporated into
        # more recent firmwares, so this is probably a thing of the past.
        #uart = machine.UART(0, 115200)
        #os.dupterm(uart)
        pass

    def print_bootscreen(self):
        """Print bootscreen.
        
        This contains important details about your device
        and the operating system running on it.


        """

        if not self.settings.get('main.logging.enabled', False):
            return

        # Todo: Maybe refactor to TerkinDatalogger.
        from uio import StringIO
        buffer = StringIO()

        def add(item=''):
            """

            :param item:  (Default value = '')

            """
            buffer.write(item)
            buffer.write('\n')

        # Program name and version.
        title = '{} {}'.format(self.name, self.version)

        add()
        add('=' * len(title))
        add(title)
        add('=' * len(title))

        # Machine runtime information.
        frequency = machine.freq() / 1000000

        add('Device id    {}'.format(self.device_id))
        add()
        add('CPU freq     {}   MHz'.format(frequency))
        try:
            import pycom
            free_heap = pycom.get_free_heap()
            add('{:13}{:>7} {}'.format('Free heap', free_heap[0] / 1000.0,
                                       'kB'))
            add('{:13}{:>7} {}'.format('Free PSRAM', free_heap[1] / 1000.0,
                                       'kB'))
        except:
            pass
        add()

        # System memory info (in bytes).
        """
        if hasattr(machine, 'info'):
            machine.info()
            add()
        """

        # TODO: Python runtime information.
        add('{:8}: {}'.format('Python', sys.version.replace('\n', '')))
        add('{:8}: {}'.format('platform', sys.platform))
        """
        >>> import os; os.uname()
        (sysname='FiPy', nodename='FiPy', release='1.20.0.rc7', version='v1.9.4-2833cf5 on 2019-02-08', machine='FiPy with ESP32', lorawan='1.0.2', sigfox='1.0.1')
        """
        runtime_info = os.uname()
        #print(dir(runtime_info))
        for key in dir(runtime_info):
            if key.startswith('__') or key.startswith('n_'):
                continue
            value = getattr(runtime_info, key)
            if callable(value):
                continue
            #print('value:', value)
            add('{:8}: {}'.format(key, value))
        add()

        # Todo: Add program authors, contributors and credits.

        log.info('\n' + buffer.getvalue())

    def power_off_lte_modem(self):
        """
        We don't use LTE yet.

        Important
        =========
        Once the LTE radio is initialized, it must be de-initialized
        before going to deepsleep in order to ensure minimum power consumption.
        This is required due to the LTE radio being powered independently and
        allowing use cases which require the system to be taken out from
        deepsleep by an event from the LTE network (data or SMS received for
        instance).

        Note
        ====
        When using the expansion board and the FiPy together, the RTS/CTS
        jumpers MUST be removed as those pins are being used by the LTE radio.
        Keeping those jumpers in place will lead to erratic operation and
        higher current consumption specially while in deepsleep.

        -- https://forum.pycom.io/topic/3090/fipy-current-consumption-analysis/17

        See also
        ========
        - https://community.hiveeyes.org/t/lte-modem-des-pycom-fipy-komplett-stilllegen/2161
        - https://forum.pycom.io/topic/4877/deepsleep-on-batteries/10
        """

        log.info('Turning off LTE modem')
        try:
            import pycom
            from network import LTE

            log.info('Turning off LTE modem on boot')
            pycom.lte_modem_en_on_boot(False)

            # Disables LTE modem completely. This presumably reduces the power
            # consumption to the minimum. Call this before entering deepsleep.
            log.info('Invoking LTE.deinit()')
            lte = LTE()
            lte.deinit(detach=False, reset=True)

        except Exception as ex:
            log.exc(ex, 'Shutting down LTE modem failed')

    def power_off_bluetooth(self):
        """We don't use Bluetooth yet."""

        if self.platform_info.vendor == self.platform_info.MICROPYTHON.Vanilla:
            log.warning(
                "FIXME: Skip touching Bluetooth on vanilla MicroPython "
                "platforms as we don't use Bluetooth yet")
            return

        log.info('Turning off Bluetooth')
        try:
            from network import Bluetooth
            bluetooth = Bluetooth()
            bluetooth.deinit()
        except Exception as ex:
            log.exc(ex, 'Shutting down Bluetooth failed')

    def hibernate(self, interval, lightsleep=False, deepsleep=False):
        """

        :param interval:
        :param lightsleep:  (Default value = False)
        :param deepsleep:  (Default value = False)

        """

        #logging.enable_logging()

        if deepsleep:

            # Prepare and invoke deep sleep.
            # https://docs.micropython.org/en/latest/library/machine.html#machine.deepsleep

            log.info('Preparing deep sleep')

            # Set wake up mode.
            self.set_wakeup_mode()

            # Invoke deep sleep.
            log.info('Entering deep sleep for {} seconds'.format(interval))
            #self.terminal.stop()
            machine.deepsleep(int(interval * 1000))

        else:

            # Adjust watchdog for interval.
            self.watchdog.adjust_for_interval(interval)

            # Invoke light sleep.
            # https://docs.micropython.org/en/latest/library/machine.html#machine.sleep
            # https://docs.micropython.org/en/latest/library/machine.html#machine.lightsleep
            #
            # As "machine.sleep" seems to be a noop on Pycom MicroPython,
            # we will just use the regular "time.sleep" here.
            # machine.sleep(int(interval * 1000))
            machine.idle()

            if lightsleep:
                log.info(
                    'Entering light sleep for {} seconds'.format(interval))
                machine.sleep(int(interval * 1000))

            else:
                # Normal wait.
                log.info('Waiting for {} seconds'.format(interval))
                time.sleep(interval)

    def resume(self):
        """ """
        try:
            from terkin.pycom import MachineResetCause
            log.info('Reset cause and wakeup reason: %s',
                     MachineResetCause().humanize())
        except Exception as ex:
            log.exc(ex, 'Could not determine reset cause and wakeup reason')

    def set_wakeup_mode(self):
        """ """

        # Set wake up parameters.
        """
        The arguments are:

        - pins: a list or tuple containing the GPIO to setup for deepsleep wakeup.

        - mode: selects the way the configured GPIOs can wake up the module.
          The possible values are: machine.WAKEUP_ALL_LOW and machine.WAKEUP_ANY_HIGH.

        - enable_pull: if set to True keeps the pull up or pull down resistors enabled
          during deep sleep. If this variable is set to True, then ULP or capacitive touch
          wakeup cannot be used in combination with GPIO wakeup.

        -- https://community.hiveeyes.org/t/deep-sleep-with-fipy-esp32-on-micropython/1792/12

        This will yield a wake up reason like::

            'wakeup_reason': {'code': 1, 'message': 'PIN'}

        """

        # Todo: ``enable_pull`` or not?

        # From documentation.
        # machine.pin_sleep_wakeup(pins=['P8'], mode=machine.WAKEUP_ALL_LOW, enable_pull=True)

        # Let's try.
        #log.info('Configuring Pin 4 for wakeup from deep sleep')
        #machine.pin_sleep_wakeup(pins=['P4'], mode=machine.WAKEUP_ALL_LOW, enable_pull=True)
        #machine.pin_sleep_wakeup(pins=['P4'], mode=machine.WAKEUP_ANY_HIGH, enable_pull=True)
        pass
Esempio n. 24
0
"""
rtc_sync - synchronize with NTTPserver
pre-condition: device connected to Wifi
2018-0529 pepo added timerecord()
2018-0520 pepo new, extracted from ws1.py
"""
from machine import RTC
from time import sleep_ms, localtime, strftime

# real-time clock
rtc = RTC()

# test if rtc needs to be synchronized
if rtc.now()[0] < 1975:
    # get the time from NTTP-server
    rtc.ntp_sync(server='nl.pool.ntp.org', tz='CET-1CEST,M3.5.0,M10.5.0/3')
    sleep_ms(500)  # small delay - trial and error


# formatted time record
def timerecord():
    return strftime("%a %d %b %Y %H:%M:%S", localtime())


# helper
def gettoday():
    return strftime("%d.%m.%Y,%H:%M:%S", localtime())


if __name__ == '__main__':
    print("It's", timerecord())
Esempio n. 25
0
class Display(object):
    IMG_DIR = '/flash/imgs'

    def __init__(self, debug=False):
        self.cfg = None
        self.rtc = RTC()
        self.debug = debug
        self.battery = Battery()

        # use this pin for debug
        self.wifi_pin = Pin("GP24", mode=Pin.IN, pull=Pin.PULL_UP)

        # Empty WDT object
        self.wdt = None

        if not debug:
            if not self.wifi_pin():
                self.wdt = WDT(timeout=20000)
            self.sd = None
        else:
            from machine import SD
            try:
                self.sd = SD()
                mount(self.sd, '/sd')
                self.logfile = open("/sd/display.log", "a")
            except OSError:
                self.sd = None
                self.logfile = None

        self.epd = EPD()

        self.log("Time left on the alarm: %dms" % self.rtc.alarm_left())

        # Don't flash when we're awake outside of debug
        heartbeat(self.debug)

    def log(self, msg, end='\n'):
        time = "%d, %d, %d, %d, %d, %d" % self.rtc.now()[:-2]
        msg = time + ", " + msg
        if self.logfile:
            self.logfile.write(msg + end)
        print(msg, end=end)

    def feed_wdt(self):
        if self.wdt:
            self.wdt.feed()

    def connect_wifi(self):
        from network import WLAN

        if not self.cfg:
            raise ValueError("Can't initialise wifi, no config")

        self.log('Starting WLAN, attempting to connect to ' + ','.join(self.cfg.wifi.keys()))
        wlan = WLAN(0, WLAN.STA)
        wlan.ifconfig(config='dhcp')
        while not wlan.isconnected():
            nets = wlan.scan()
            for network in nets:
                if network.ssid in self.cfg.wifi.keys():
                    self.log('Connecting to ' + network.ssid)
                    self.feed_wdt() # just in case
                    wlan.connect(ssid=network.ssid, auth=(network.sec, self.cfg.wifi[network.ssid]))
                    while not wlan.isconnected():
                        idle()
                    break

            self.feed_wdt() # just in case
            sleep_ms(2000)

        self.log('Connected as %s' % wlan.ifconfig()[0])

    @staticmethod
    def reset_cause():
        import machine
        val = machine.reset_cause()
        if val == machine.POWER_ON:
            return "power"
        elif val == machine.HARD_RESET:
            return "hard"
        elif val == machine.WDT_RESET:
            return "wdt"
        elif val == machine.DEEPSLEEP_RESET:
            return "sleep"
        elif val == machine.SOFT_RESET:
            return "soft"

    def set_alarm(self, now, json_metadata):
        import json
        json_dict = json.loads(json_metadata)

        # Now we know the time too
        self.rtc = RTC(datetime=now)
        list_int = json_dict["wakeup"][:6]
        time_str = ",".join([str(x) for x in list_int])

        self.log("Setting alarm for " + time_str)
        self.rtc.alarm(time=tuple(list_int))

        if self.rtc.alarm_left() == 0:
            self.log("Alarm failed, setting for +1 hour")
            self.rtc.alarm(time=3600000)

        del json

    def display_file_image(self, file_obj):
        towrite = 15016
        max_chunk = 250
        while towrite > 0:
            c = max_chunk if towrite > max_chunk else towrite
            buff = file_obj.read(c)
            self.epd.upload_image_data(buff, delay_us=2000)
            self.feed_wdt()
            towrite -= c

        self.epd.display_update()

    def display_no_config(self):
        self.log("Displaying no config msg")
        with open(Display.IMG_DIR + '/no_config.bin', 'rb') as pic:
            self.display_file_image(pic)

    def display_low_battery(self):
        self.log("Displaying low battery msg")
        with open(Display.IMG_DIR + '/low_battery.bin', 'rb') as pic:
            self.display_file_image(pic)

    def display_cannot_connect(self):
        self.log("Displaying no server comms msg")
        with open(Display.IMG_DIR + '/no_server.bin', 'rb') as pic:
            self.display_file_image(pic)

    def display_no_wifi(self):
        self.log("Displaying no wifi msg")
        with open(Display.IMG_DIR + '/no_wifi.bin', 'rb') as pic:
            self.display_file_image(pic)

    def check_battery_level(self):
        now_batt = 200
        last_batt = self.battery.battery_raw()
        while now_batt > last_batt:
            sleep_ms(50)
            last_batt = now_batt
            self.feed_wdt()
            now_batt = self.battery.battery_raw()
            self.log("Battery value: %d (%d)" % (self.battery.value(), self.battery.battery_raw()))

        if not self.battery.safe():
            self.log("Battery voltage (%d) low! Turning off" % self.battery.battery_raw())
            self.feed_wdt()
            self.display_low_battery()
            return False
        else:
            self.log("Battery value: %d (%d)" % (self.battery.value(), self.battery.battery_raw()))
        return True

    def run_deepsleep(self):

        if not self.run():
            # RTC wasn't set, try to sleep forever
            self.rtc.alarm(time=2000000000)

        # Set the wakeup (why do it earlier?)
        rtc_i = self.rtc.irq(trigger=RTC.ALARM0, wake=DEEPSLEEP)

        self.log("Going to sleep, waking in %dms" % self.rtc.alarm_left())

        # Close files on the SD card
        if self.sd:
            self.logfile.close()
            self.logfile = None
            unmount('/sd')
            self.sd.deinit()

        # Turn the screen off
        self.epd.disable()

        if not self.wifi_pin():
            # Basically turn off
            deepsleep()
        else:
            self.log("DEBUG MODE: Staying awake")
            pass
            # Do nothing, allow network connections in

    def run(self):

        woken = self.wifi_pin()
        self.epd.enable()

        if not self.check_battery_level():
            return False

        try:
            self.epd.get_sensor_data()
        except ValueError:
            self.log("Can't communicate with display, flashing light and giving up")
            heartbeat(True)
            sleep_ms(15000)
            return True

        if self.rtc.alarm_left() > 0:
            self.log("Woken up but the timer is still running, refreshing screen only")
            self.epd.display_update()
            self.feed_wdt()
            return True

        try:
            self.cfg = Config.load(sd=self.sd)
            self.log("Loaded config")
        except (OSError, ValueError) as e:
            self.log("Failed to load config: " + str(e))
            self.display_no_config()
            try:
                self.connect_wifi()
            except:
                pass # everything

            while True:
                sleep_ms(10)
                self.feed_wdt()

        self.feed_wdt()

        self.connect_wifi()

        content = b''
        try:
            self.log("Connecting to server %s:%d" % (self.cfg.host, self.cfg.port))
            c = Connect(self.cfg.host, self.cfg.port, debug=self.debug)

            self.feed_wdt()

            cause = Display.reset_cause()
            if woken:
                cause = "user"

            self.log("Reset cause: " + cause)

            if len(self.cfg.upload_path) > 0:
                temp = self.epd.get_sensor_data() # we read this already
                c.post(self.cfg.upload_path,
                       battery=self.battery.value(),
                       reset=cause,
                       screen=temp)

            self.log("Fetching metadata from " + self.cfg.metadata_path)
            metadata = c.get_quick(self.cfg.metadata_path, max_length=1024, path_type='json')

            # This will set the time to GMT, not localtime
            self.set_alarm(c.last_fetch_time, metadata)

            self.feed_wdt()
            del metadata
            del self.battery
            self.log("Fetching image from " + self.cfg.image_path)
            self.epd.image_erase_frame_buffer()
            self.feed_wdt()

            length, socket = c.get_object(self.cfg.image_path)

            if length != 15016:
                raise ValueError("Wrong data size for image: %d" % length)

            self.feed_wdt()

        except (RuntimeError, ValueError, OSError) as e:
            self.log("Failed to get remote info: " + str(e))
            self.display_cannot_connect()
            self.rtc.alarm(time=3600000)
            return True

        sleep_ms(1000) # How do we make the write to display more reliable?
        self.feed_wdt()
        self.log("Uploading to display")
        self.display_file_image(socket)
        c.get_object_done() # close off socket

        if self.cfg.src == "sd":
            # If we've got a working config from SD instead of flash
            self.log("Transferring working config")
            Config.transfer()
            self.log("SUCCESS")

        self.log("Finished. Mem free: %d" % gc.mem_free())
        return True
class NotificationQueue:
    VIBRATION_STARTED = 1
    VIBRATION_STOPPED = 2
    UPTIME = 3
    AMBIENT = 4
    VERSION = 5
    MAGNITUDE = 6

    def __init__(self):
        self._deque = deque()
        self._lock = allocate_lock()
        self._rtc = RTC()

    def _push(self, notification):
        with self._lock:
            self._deque.appendleft(notification)

    def pop(self):
        r = []
        with self._lock:
            while self._deque:
                r.append(self._deque.popright())
        return r

    def timestamp(self):
        sec = utime.time()
        usec = self._rtc.now()[6]
        # print('{} {} {}'.format(sec, usec, sec * 1000 + int(usec / 1000)))
        return sec * 1000 + int(usec / 1000)

    def push_vibration_started(self):
        self._push(
            Notification(type=NotificationQueue.VIBRATION_STARTED,
                         data=None,
                         timestamp=self.timestamp()))

    def push_vibration_stopped(self, duration):
        self._push(
            Notification(type=NotificationQueue.VIBRATION_STOPPED,
                         data=int(duration),
                         timestamp=self.timestamp()))

    def push_version(self, version):
        self._push(
            Notification(type=NotificationQueue.VERSION,
                         data=version,
                         timestamp=self.timestamp()))

    def push_uptime(self, uptime_sec):
        # uptime_sec = uptime_ms // 1000
        uptime_hours = uptime_sec // (60 * 60)
        uptime_sec -= uptime_hours * (60 * 60)
        uptime_min = uptime_sec // 60
        uptime_sec -= uptime_min * 60
        self._push(
            Notification(type=NotificationQueue.UPTIME,
                         data='{}h {}m {}s'.format(uptime_hours, uptime_min,
                                                   uptime_sec),
                         timestamp=self.timestamp()))

    def push_ambient(self, temperature, humidity, pressure, voltage):
        self._push(
            Notification(type=NotificationQueue.AMBIENT,
                         data=(temperature, humidity, pressure, voltage),
                         timestamp=self.timestamp()))

    def push_mangnitudes(self, magnitudes):
        if not magnitudes:
            return
        self._push(
            Notification(type=NotificationQueue.MAGNITUDE,
                         data=ujson.dumps(magnitudes),
                         timestamp=self.timestamp()))

    def __len__(self):
        return len(self._deque)

    def __bool__(self):
        return bool(self._deque)

    def __iter__(self):
        yield from self._deque

    def __str__(self):
        return 'deque({})'.format(self._deque)
Esempio n. 27
0
class ErrorLogService(object):
    def __init__(self):
        self.serviceID = 8
        self.rtc = 0
        self.enabled = False
        self.namesFiles = dict()
        self.warningLog = dict()
        self.connectionService = 0
        self.descriptionsErrors = dict()
        self.descriptionsWarnings = dict()
        self.errorsCounter = dict()
        self.warningsCounter = dict()
        self.lock = 0

    def confService(self, atributes):
        self.connectionService = atributes['connectionService']
        self.lock = atributes['lock']
        self.rtc = RTC()
        if ('errorFile' in atributes) and ('warningFile' in atributes) and (
                'errorsList' in atributes) and ('warningsLits' in atributes):
            if str(atributes['errorFile']).isdigit():  #Error si es un numero
                self.regError(self.serviceID,
                              -9)  #Incorrect AtributeValue Error
            else:
                self.namesFiles.setdefault('errorFile', atributes['errorFile'])
            if str(atributes['warningFile']).isdigit():  #Error si es un numero
                self.regError(self.serviceID,
                              -9)  #Incorrect AtributeValue Error
            else:
                self.namesFiles.setdefault('warningFile',
                                           atributes['warningFile'])
            if str(atributes['errorsList']).isdigit():  #Error si es un numero
                self.regError(self.serviceID,
                              -9)  #Incorrect AtributeValue Error
            else:
                self.descriptionsErrors = atributes['errorsList']
            if str(atributes['warningsLits']).isdigit(
            ):  #Error si es un numero
                self.regError(self.serviceID,
                              -9)  #Incorrect AtributeValue Error
            else:
                self.descriptionsWarnings = atributes['warningsLits']
        else:
            self.regError(self.serviceID, -2)  #ConfFile Error

    def updateAtribute(self, atribute, newValue):
        if not str(atribute).isdigit() and atribute == 'errorFile':
            self.namesFiles.update({atribute: newValue})
        elif not str(atribute).isdigit() and atribute == 'warningFile':
            self.namesFiles.update({atribute: newValue})
        elif not str(atribute).isdigit() and atribute == 'descriptionsErrors':
            self.descriptionsErrors = newValue
        elif not str(
                atribute).isdigit() and atribute == 'descriptionsWarnings':
            self.descriptionsWarnings = newValue
        else:
            self.regError(self.serviceID, -8)  #Incorrect Atribute Error code

    def connect(self, atributes):
        self.confService(atributes)
        self.enabled = True

    def regError(self, serviceID, error):
        if self.enabled == True:
            #fileError = open(self.namesFiles['errorFile'], "a")
            #fileWarning = open(self.namesFiles['warningFile'], "a")
            #fileError.close()
            #fileWarning.close()
            time = ""
            dataSend = dict()
            dataSend.setdefault('hour', self.rtc.now()[3])
            dataSend.setdefault('minute', self.rtc.now()[4])
            dataSend.setdefault('seconds', self.rtc.now()[5])
            time += str(dataSend['hour'])
            time += ':'
            time += str(dataSend['minute'])
            time += ':'
            time += str(dataSend['seconds'])
            if error in self.descriptionsErrors:
                description = self.descriptionsErrors.setdefault(error)
                self.updateFile(self.namesFiles.get('errorFile'))
                fileError = open(self.namesFiles.get('errorFile'), "a")
                fileError.write(time + " " + str(serviceID) + " " +
                                description + "/n")
                fileError.close()
                if error not in self.errorsCounter:
                    self.errorsCounter.setdefault(description, 0)
                counter = self.errorsCounter.setdefault(description)
                counter = counter + 1
                self.errorsCounter.setdefault(description, counter)
                dataSend.setdefault('description', description)
                dataSend.setdefault('counter',
                                    self.errorsCounter.setdefault(description))
                self.connectionService.sendPackage('errorWarning', dataSend)
            if error in self.descriptionsWarnings:
                description = self.descriptionsWarnings[error].get(
                    'description')
                counter = self.counterCheck(
                    serviceID, error, description,
                    dataSend)  #Comprobación de contador
                #self.updateFile(self.namesFiles.get('warningFile'))
                #self.lock.acquire()
                #fileWarning = open(self.namesFiles.get('warningFile'), "a")
                #prueba = time + " " + str(serviceID) + " " + description + " " + str(counter) + "\n"
                #fileWarning.write(prueba)
                #fileWarning.close()
                #self.lock.release()

    def counterCheck(self, serviceID, error, description, dataSend):
        if serviceID not in self.warningLog:
            aux = dict()
            self.warningLog.setdefault(serviceID, aux)
        if error not in self.warningLog[serviceID]:
            self.warningLog[serviceID].setdefault(error, 1)
        counter = self.warningLog[serviceID].setdefault(
            error)  #Comprueba cuantas veces ha sucedido "error"
        if (counter < self.descriptionsWarnings[error].get('erLimit')):
            counter += 1
            self.warningLog[serviceID].update({error: counter})
        else:
            if description not in self.warningsCounter:
                self.warningsCounter.setdefault(description, 0)
            notifyCounter = self.warningsCounter.setdefault(description)
            notifyCounter = notifyCounter + 1
            self.warningsCounter.update({description: notifyCounter})
            dataSend.setdefault('description', description)
            dataSend.setdefault('counter',
                                self.warningsCounter.setdefault(description))
            self.connectionService.sendPackage('errorWarning', dataSend)
            counter = 1
            self.warningLog[serviceID].update({error: counter})
        return counter

    def updateFile(self, fileName):
        self.lock.acquire()
        f = open(fileName, "r")
        lines = f.readlines()
        f.close()
        if len(
                lines
        ) == 10:  #Si la longitud del fichero era 10, se crea de nuevo vacio copiando solo las lineas 1-9
            fileaux = open(fileName, "w")
            i = 1
            while i < 10:
                fileaux.write(lines[i])
                i += 1
            fileaux.close()
        self.lock.release()

    def notifyToServer(self, dataSend):
        self.connectionService.sendPackage('errorWarning', dataSend)

    def disconnect(self):
        self.enabled = False

    def serviceEnabled(self):
        return self.enabled
Esempio n. 28
0
print(os.getcwd())
# create a new file
f = open('test.txt', 'w')
n_w = f.write(test_bytes)
print(n_w == len(test_bytes))
f.close()
f = open('test.txt', 'r')
r = bytes(f.read(), 'ascii')
# check that we can write and read it correctly
print(r == test_bytes)
f.close()
os.remove('test.txt')
os.chdir('..')
os.rmdir('test')

ls = os.listdir()
print('test' not in ls)
print(ls)

# test the real time clock
rtc = RTC()
while rtc.now()[6] > 800:
    pass

time1 = rtc.now()
time.sleep_ms(1000)
time2 = rtc.now()
print(time2[5] - time1[5] == 1)
print(time2[6] - time1[6] < 5000) # microseconds

Esempio n. 29
0
from machine import RTC

rtc = RTC()
print(rtc.now())
Esempio n. 30
0
os.chdir("/flash/test")
print(os.getcwd())
# create a new file
f = open("test.txt", "w")
n_w = f.write(test_bytes)
print(n_w == len(test_bytes))
f.close()
f = open("test.txt", "r")
r = bytes(f.read(), "ascii")
# check that we can write and read it correctly
print(r == test_bytes)
f.close()
os.remove("test.txt")
os.chdir("..")
os.rmdir("test")

ls = os.listdir()
print("test" not in ls)
print(ls)

# test the real time clock
rtc = RTC()
while rtc.now()[6] > 800:
    pass

time1 = rtc.now()
time.sleep_ms(1000)
time2 = rtc.now()
print(time2[5] - time1[5] == 1)
print(time2[6] - time1[6] < 5000)  # microseconds
class ConnectionService(object):
    def __init__(self):
        self.serviceID = 7
        self.conexion = 0
        self.rtc = 0
        self.enabled = False
        self.euiGateway = 0
        self.keyGateway = 0

    def confService(self, atributes):
        self.rtc = RTC()
        self.euiGateway = atributes['euiGateway']
        self.keyGateway = atributes['keyGateway']
        lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868
                    )  # Initialise LoRa in LORAWAN mode. Europe = LoRa.EU868
        # create an OTAA authentication parameters
        app_eui = ubinascii.unhexlify(self.euiGateway)  # eui del Gateway
        app_key = ubinascii.unhexlify(self.keyGateway)  # key del gateway
        lora.join(
            activation=LoRa.OTAA, auth=(app_eui, app_key),
            timeout=0)  # join a network using OTAA (Over the Air Activation)
        while not lora.has_joined(
        ):  # wait until the module has joined the network
            time.sleep(2.5)
            #print('Not yet joined...')
        self.conexion = socket.socket(socket.AF_LORA,
                                      socket.SOCK_RAW)  # create a LoRa socket
        self.conexion.setsockopt(socket.SOL_LORA, socket.SO_DR,
                                 5)  # set the LoRaWAN data rate

    def updateAtribute(self, atribute, newValue):
        if atribute == 'euiGateway':
            self.euiGateway = newValue
        elif atribute == 'keyGateway':
            self.keyGateway = newValue
        else:
            self.errorLog.regError(self.serviceID,
                                   -8)  #Incorrect Atribute Error code

    def connect(self, atributes):
        self.confService(atributes)
        self.sendPackage('connect', '')
        self.enabled = True

    def disconnect(self):
        self.enabled = False
        self.sendPackage('disconnect', '')

    def serviceEnabled(self):
        return self.enabled

    def sendPackage(self, typePackage, data):
        dataSend = ''
        if typePackage == 'sample':  # Mensaje de muestras
            dataSend = self.samplePackage(data)
        if typePackage == 'location':  # Mensaje de muestras
            dataSend = self.locationPackage(data)
        if typePackage == 'time':  # Mensaje de muestras
            dataSend = self.timePackage(data)
        if typePackage == 'connect':  # Mensaje para darse de anta en thingsboards
            dataSend = self.connectPackage(data)
        if typePackage == 'disconnect':  # Mensaje para darse de baja en thingsboards
            dataSend = self.disconnectPackage(data)
        if typePackage == 'errorWarning':  # Mensaje de error
            dataSend = self.errorWarningPackage(data)
        self.send(dataSend)

    def send(self, dataSend):
        self.conexion.setblocking(True)  # make the socket blocking
        self.conexion.send(dataSend)  # send some data
        self.conexion.setblocking(False)  # make the socket non-blocking
        dataRecv = self.conexion.recv(64)  # get any data received (if any...)
        collectMemory()

    def samplePackage(self, data):
        dataSend = ''
        dataSend += str(data.get('hour'))
        dataSend += ' '
        dataSend += str(data.get('minute'))
        dataSend += ' '
        dataSend += str(data.get('seconds'))
        dataSend += ' '
        dataSend += '0'  # Type of package 0 = sample

        if 3 in data:
            dataSend += ' '
            dataSend += str(1)
        else:
            dataSend += ' '
            dataSend += str(0)

        if 4 in data:
            dataSend += ' '
            dataSend += str(1)
        else:
            dataSend += ' '
            dataSend += str(0)

        if 5 in data:
            dataSend += ' '
            dataSend += str(1)
        else:
            dataSend += ' '
            dataSend += str(0)

        if 6 in data:
            dataSend += ' '
            dataSend += str(1)
        else:
            dataSend += ' '
            dataSend += str(0)

        if 3 in data:
            dataSend += ' '
            dataSend += str(data.get(3))
        if 4 in data:
            dataSend += ' '
            dataSend += str(data.get(4))
        if 5 in data:
            dataSend += ' '
            dataSend += str(data.get(5))
        if 6 in data:
            dataSend += ' '
            dataSend += str(data.get(6))

        return dataSend

    def locationPackage(self, data):
        dataSend = ''
        dataSend += str(data.get('hour'))
        dataSend += ' '
        dataSend += str(data.get('minute'))
        dataSend += ' '
        dataSend += str(data.get('seconds'))
        dataSend += ' '
        dataSend += '1'  # Type of package 1 = location
        dataSend += ' '
        dataSend += str(data['longitude'])
        dataSend += ' '
        dataSend += str(data['latitude'])
        dataSend += ' '
        dataSend += str(data['height'])
        return dataSend

    def timePackage(self, data):
        dataSend = ''
        dataSend += str(data.get('hour'))
        dataSend += ' '
        dataSend += str(data.get('minute'))
        dataSend += ' '
        dataSend += str(data.get('seconds'))
        dataSend += ' '
        dataSend += '2'  # Type of package 2 = Time
        dataSend += ' '
        dataSend += str(data.get('hour'))  # Hora Inicio
        dataSend += ' '
        dataSend += str(data.get('minute'))  # Minuto Inicio
        dataSend += ' '
        dataSend += str(data.get('seconds'))  # Segundo Inicio
        return dataSend

    def connectPackage(self, data):
        dataSend = ''
        dataSend += str(self.rtc.now()[3])
        dataSend += ' '
        dataSend += str(self.rtc.now()[4])
        dataSend += ' '
        dataSend += str(self.rtc.now()[5])
        dataSend += ' '
        dataSend += '3'  # Type of package 3 = connect
        return dataSend

    def disconnectPackage(self, data):
        dataSend = ''
        dataSend += str(self.rtc.now()[3])
        dataSend += ' '
        dataSend += str(self.rtc.now()[4])
        dataSend += ' '
        dataSend += str(self.rtc.now()[5])
        dataSend += ' '
        dataSend += '4'  # Type of package 4 = disconnect
        return dataSend

    def errorWarningPackage(self, data):
        dataSend = ''
        dataSend += str(data.get('hour'))
        dataSend += ' '
        dataSend += str(data.get('minute'))
        dataSend += ' '
        dataSend += str(data.get('seconds'))
        dataSend += ' '
        dataSend += '5'  # Type of package 5 = errorWarning
        dataSend += ' '
        dataSend += data.get('description')  # DescriptionError
        dataSend += ' '
        dataSend += str(data.get('counter'))  # Counter of Error
        return dataSend
Esempio n. 32
0
class TerkinDevice:
    def __init__(self, name=None, version=None, settings=None):

        self.name = name
        self.version = version
        self.settings = settings

        # Conditionally enable terminal on UART0. Default: False.
        self.terminal = Terminal(self.settings)
        self.terminal.start()

        self.device_id = get_device_id()

        self.networking = None
        self.telemetry = None

        self.wdt = None
        self.rtc = None

        self.status = DeviceStatus()

    @property
    def appname(self):
        return '{} {}'.format(self.name, self.version)

    def start_networking(self):
        log.info('Starting networking')

        from terkin.network import NetworkManager, WiFiException

        self.networking = NetworkManager(device=self, settings=self.settings)

        # Start WiFi.
        try:
            self.networking.start_wifi()

            # Wait for network interface to come up.
            self.networking.wait_for_nic()

            self.status.networking = True

        except WiFiException:
            log.error('Network connectivity not available, WiFi failed')
            self.status.networking = False

        # Start UDP server for pulling device into maintenance mode.
        self.networking.start_modeserver()

        # Initialize LoRa device.
        if self.settings.get('networking.lora.antenna_attached'):
            try:
                self.networking.start_lora()
            except:
                log.exception('Unable to start LoRa subsystem')
        else:
            log.info(
                "[LoRa] Disabling LoRa interface as no antenna has been attached. "
                "ATTENTION: Running LoRa without antenna will wreck your device."
            )

        # Inform about networking status.
        #self.networking.print_status()

    def start_watchdog(self):
        """
        The WDT is used to restart the system when the application crashes and
        ends up into a non recoverable state. After enabling, the application
        must "feed" the watchdog periodically to prevent it from expiring and
        resetting the system.
        """
        # https://docs.pycom.io/firmwareapi/pycom/machine/wdt.html

        if not self.settings.get('main.watchdog.enabled', False):
            log.info('Skipping watchdog timer (WDT)')
            return

        watchdog_timeout = self.settings.get('main.watchdog.timeout', 10000)
        log.info('Starting the watchdog timer (WDT) with timeout {}ms'.format(
            watchdog_timeout))

        from machine import WDT
        self.wdt = WDT(timeout=watchdog_timeout)

        # Feed Watchdog once.
        self.wdt.feed()

    def feed_watchdog(self):
        if self.wdt is not None:
            log.info('Feeding Watchdog')
            self.wdt.feed()

    def start_rtc(self):
        """
        The RTC is used to keep track of the date and time.
        """
        # https://docs.pycom.io/firmwareapi/pycom/machine/rtc.html
        # https://medium.com/@chrismisztur/pycom-uasyncio-installation-94931fc71283
        import time
        from machine import RTC
        self.rtc = RTC()
        # TODO: Use values from configuration settings here.
        self.rtc.ntp_sync("pool.ntp.org", 360)
        while not self.rtc.synced():
            time.sleep_ms(50)
        log.info('RTC: %s', self.rtc.now())

    def run_gc(self):
        """
        Run a garbage collection.
        https://docs.pycom.io/firmwareapi/micropython/gc.html
        """
        import gc
        gc.collect()

    def configure_rgb_led(self):
        """
        https://docs.pycom.io/tutorials/all/rgbled.html
        """
        import pycom

        # Enable or disable heartbeat.
        rgb_led_heartbeat = self.settings.get('main.rgb_led.heartbeat', True)
        pycom.heartbeat(rgb_led_heartbeat)
        pycom.heartbeat_on_boot(rgb_led_heartbeat)

        # Alternative signalling.
        # Todo: Run this in a separate thread in order not to delay execution of main program flow.
        if not rgb_led_heartbeat:
            for _ in range(2):
                pycom.rgbled(0x001100)
                time.sleep(0.15)
                pycom.rgbled(0x000000)
                time.sleep(0.10)

    def power_off_lte_modem(self):
        """
        We don't use LTE yet.

        https://community.hiveeyes.org/t/lte-modem-des-pycom-fipy-komplett-stilllegen/2161
        https://forum.pycom.io/topic/4877/deepsleep-on-batteries/10
        """

        import pycom
        """
        if not pycom.lte_modem_en_on_boot():
            log.info('Skip turning off LTE modem')
            return
        """

        log.info('Turning off LTE modem')
        try:
            from network import LTE

            # Invoking this will cause `LTE.deinit()` to take around 6(!) seconds.
            #log.info('Enabling LTE modem on boot')
            #pycom.lte_modem_en_on_boot(True)

            log.info('Turning off LTE modem on boot')
            pycom.lte_modem_en_on_boot(False)

            log.info('Invoking LTE.deinit()')
            lte = LTE()
            lte.deinit()

        except:
            log.exception('Shutting down LTE modem failed')

    def power_off_bluetooth(self):
        """
        We don't use Bluetooth yet.
        """
        log.info('Turning off Bluetooth')
        try:
            from network import Bluetooth
            bluetooth = Bluetooth()
            bluetooth.deinit()
        except:
            log.exception('Shutting down Bluetooth failed')

    def start_telemetry(self):
        log.info('Starting telemetry')

        self.telemetry = TelemetryManager()

        # Read all designated telemetry targets from configuration settings.
        telemetry_targets = self.settings.get('telemetry.targets')

        # Compute list of all _enabled_ telemetry targets.
        telemetry_candidates = []
        for telemetry_target in telemetry_targets:
            if telemetry_target.get('enabled', False):
                telemetry_candidates.append(telemetry_target)

        # Create adapter objects for each enabled telemetry target.
        for telemetry_target in telemetry_candidates:
            try:
                self.create_telemetry_adapter(telemetry_target)
                self.feed_watchdog()

            except:
                log.exception(
                    'Creating telemetry adapter failed for target: %s',
                    telemetry_target)

    def create_telemetry_adapter(self, telemetry_target):
        # Create adapter object.
        telemetry_adapter = TelemetryAdapter(
            device=self,
            endpoint=telemetry_target['endpoint'],
            address=telemetry_target.get('address'),
            data=telemetry_target.get('data'),
            topology=telemetry_target.get('topology'),
            format=telemetry_target.get('format'),
            content_encoding=telemetry_target.get('encode'),
        )

        # Setup telemetry adapter.
        telemetry_adapter.setup()

        self.telemetry.add_adapter(telemetry_adapter)

    def enable_serial(self):
        # Disable these two lines if you don't want serial access.
        # The Pycom forum tells us that this is already incorporated into
        # more recent firmwares, so this is probably a thing of the past.
        #uart = machine.UART(0, 115200)
        #os.dupterm(uart)
        pass

    def print_bootscreen(self):
        """
        Print bootscreen.

        This contains important details about your device
        and the operating system running on it.
        """

        if not self.settings.get('main.logging.enabled', False):
            return

        # Todo: Maybe refactor to TerkinDatalogger.
        from uio import StringIO
        buffer = StringIO()

        def add(item=''):
            buffer.write(item)
            buffer.write('\n')

        # Program name and version.
        title = '{} {}'.format(self.name, self.version)

        add()
        add('=' * len(title))
        add(title)
        add('=' * len(title))

        # Machine runtime information.
        add('CPU freq     {} MHz'.format(machine.freq() / 1000000))
        add('Device id    {}'.format(self.device_id))
        add()

        # System memory info (in bytes)
        machine.info()
        add()

        # TODO: Python runtime information.
        add('{:8}: {}'.format('Python', sys.version))
        """
        >>> import os; os.uname()
        (sysname='FiPy', nodename='FiPy', release='1.20.0.rc7', version='v1.9.4-2833cf5 on 2019-02-08', machine='FiPy with ESP32', lorawan='1.0.2', sigfox='1.0.1')
        """
        runtime_info = os.uname()
        for key in dir(runtime_info):
            if key == '__class__':
                continue
            value = getattr(runtime_info, key)
            #print('value:', value)
            add('{:8}: {}'.format(key, value))
        add()
        add()

        # Todo: Add program authors, contributors and credits.

        log.info('\n' + buffer.getvalue())

    def power_off(self):
        self.networking.stop()

    def hibernate(self, interval, deepsleep=False):

        #logging.enable_logging()

        if deepsleep:

            # Prepare and invoke deep sleep.
            # https://docs.micropython.org/en/latest/library/machine.html#machine.deepsleep

            log.info('Preparing deep sleep')

            # Set wake up mode.
            self.set_wakeup_mode()

            # Invoke deep sleep.
            log.info('Entering deep sleep for {} seconds'.format(interval))
            self.terminal.stop()
            machine.deepsleep(int(interval * 1000))

        else:

            log.info('Entering light sleep for {} seconds'.format(interval))

            # Invoke light sleep.
            # https://docs.micropython.org/en/latest/library/machine.html#machine.sleep
            # https://docs.micropython.org/en/latest/library/machine.html#machine.lightsleep
            #
            # As "machine.sleep" seems to be a noop on Pycom MicroPython,
            # we will just use the regular "time.sleep" here.
            # machine.sleep(int(interval * 1000))
            time.sleep(interval)

    def resume(self):
        log.info('Reset cause and wakeup reason: %s',
                 MachineResetCause.humanize())

    def set_wakeup_mode(self):

        # Set wake up parameters.
        """
        The arguments are:

        - pins: a list or tuple containing the GPIO to setup for deepsleep wakeup.

        - mode: selects the way the configured GPIOs can wake up the module.
          The possible values are: machine.WAKEUP_ALL_LOW and machine.WAKEUP_ANY_HIGH.

        - enable_pull: if set to True keeps the pull up or pull down resistors enabled
          during deep sleep. If this variable is set to True, then ULP or capacitive touch
          wakeup cannot be used in combination with GPIO wakeup.

        -- https://community.hiveeyes.org/t/deep-sleep-with-fipy-esp32-on-micropython/1792/12

        This will yield a wake up reason like::

            'wakeup_reason': {'code': 1, 'message': 'PIN'}

        """

        # Todo: ``enable_pull`` or not?

        # From documentation.
        # machine.pin_sleep_wakeup(pins=['P8'], mode=machine.WAKEUP_ALL_LOW, enable_pull=True)

        # Let's try.
        #machine.pin_sleep_wakeup(pins=['P8'], mode=machine.WAKEUP_ALL_LOW, enable_pull=False)
        pass
Esempio n. 33
0
for _ in range(3):
    print_iv("cpu on, wifi connected")
    sleep(1)

# fetch internet time

t_start = ticks_ms()
rtc = RTC()
rtc.ntp_sync(server="hr.pool.ntp.org")
while not rtc.synced():
    continue
t_stop = ticks_ms()

print("{:8.3}s for connecting getting internet time".format(
    ticks_diff(t_stop, t_start) / 1e3))
print(strftime("%c", rtc.now()))

for _ in range(3):
    print_iv("cpu on, wifi connected")
    sleep(1)

wlan.disconnect()

for _ in range(3):
    print_iv("cpu on, wifi disconnected")
    sleep(1)

wlan.active(False)

for _ in range(3):
    print_iv("cpu on, wlan inactive")
Esempio n. 34
0
class udatetime:
    def __init__(self):
        self.__datetime = Datetime()
        self.__timetuple = ()
        self.__seconds = 0
        self.__rtc = RTC()
        self.__rtc.ntp_sync("pool.ntp.org")  # sync to UTC time
        while not self.__rtc.synced():
            sleep(1)

    # get_current_time() will be the core method to be called to get latest datetime
    # and update the values of corresponding attributes
    def get_current_time(self):
        self.__timetuple = self.__rtc.now()
        self.__datetime.year, self.__datetime.month, self.__datetime.day, self.__datetime.hour, self.__datetime.minute, self.__datetime.second, *args = self.__timetuple

    def utcnow(self) -> udatetime:
        self.get_current_time()
        return self

    def utc_seconds(self) -> int:
        self.get_current_time()
        self.__seconds = utime.mktime(self.__timetuple)
        return self.__seconds

    def year(self) -> int:
        return self.__datetime.year

    def month(self) -> int:
        return self.__datetime.month

    def day(self) -> int:
        return self.__datetime.day

    def hour(self) -> int:
        return self.__datetime.hour

    def minute(self) -> int:
        return self.__datetime.minute

    def second(self) -> int:
        return self.__datetime.second

    def strftime(self, dt_format: str) -> str:

        dt_map = {
            "%Y": "{:4}".format(self.__datetime.year),
            "%m": "{:02}".format(self.__datetime.month),
            "%d": "{:02}".format(self.__datetime.day),
            "%H": "{:02}".format(self.__datetime.hour),
            "%M": "{:02}".format(self.__datetime.minute),
            "%S": "{:02}".format(self.__datetime.second)
        }

        for key, value in dt_map.items():
            if key in dt_format:
                dt_format = dt_format.replace(key, value)

        return dt_format

    def __str__(self) -> str:
        return "{:4}-{:02}-{:02}T{:02}:{:02}:{:02}Z".format(
            self.__datetime.year, self.__datetime.month, self.__datetime.day,
            self.__datetime.hour, self.__datetime.minute,
            self.__datetime.second)
Esempio n. 35
0
#l76 = L76GNSS(py, timeout=30)

# Initialize LoRa in LORAWAN mode.
# Please pick the region that matches where you are using the device:
# Asia = LoRa.AS923
# Australia = LoRa.AU915
# Europe = LoRa.EU868
# United States = LoRa.US915
lora = LoRa(mode=LoRa.LORAWAN,
            region=LoRa.EU868,
            adr=True,
            public=True,
            tx_retries=2,
            device_class=LoRa.CLASS_A)

print('Boot at ', rtc.now())
print('Radio EUI=', binascii.hexlify(lora.mac()))
# create an OTAA authentication parameters

# Device ID: 240AC400C0CE
# LoRa MAC: 70B3D5499BDBEE28 (28EEDB9B49D5B370)

dev_eui = binascii.unhexlify('70B3D5499BB14241')
app_eui = binascii.unhexlify('ADA4DAE3AC12676B')
app_key = binascii.unhexlify('B0B4D2D8C7FA38548B11B0282A189B75')

RED = 0xff0000
GREEN = 0x00ff00
BLUE = 0x0000ff
ORANGE = 0xffa500
CYAN = 0x00B7EB
Esempio n. 36
0
import time
import socket
import time

from machine import RTC
TZ = 0
print("sync rtc via ntp, TZ=", TZ)
rtc = RTC()
print("synced?", rtc.synced())
rtc.ntp_sync('nl.pool.ntp.org')
print("synced?", rtc.synced())
#time.sleep_ms(750)
time.timezone(TZ * 3600)
i = 0
while True:
    if rtc.synced():
        print("rtc is synced after", i / 1000, "s")
        # if rtc.now()[0] == 1970:
        #     print()
        break
    if i % 100 == 0:
        print(".", end="")
    time.sleep_ms(1)
print("rtc.now", rtc.now())
print("time.gmtime", time.gmtime())
print("time.localtime", time.localtime())
print("gmt  ", end=" ")
print("local", end=" ")
Esempio n. 37
0
'''
RTC test for the CC3200 based boards.
'''

from machine import RTC
import os
import time

mch = os.uname().machine
if not 'LaunchPad' in mch and not 'WiPy' in mch:
    raise Exception('Board not supported!')

rtc = RTC()
print(rtc)
print(rtc.now()[:6])

rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None))
print(rtc.now()[:6])

rtc.deinit()
print(rtc.now()[:6])

rtc.init((2015, 8, 29, 9, 0, 0, 0, None))
print(rtc.now()[:6])
seconds = rtc.now()[5]
time.sleep_ms(1000)
print(rtc.now()[5] - seconds == 1)
seconds = rtc.now()[5]
time.sleep_ms(2000)
print(rtc.now()[5] - seconds == 2)