Beispiel #1
0
def isTime(lastTime, frequency):
    """
    Will calculate whether to do something based on how frequent the action
    should be. E.g. if something should happen every 6 seconds and the last
    time it was completed was 5 seconds ago this will return False.
    
    Inputs:
        * lastTime => The timestamp of the last time the action was completed.
                      [datetime.datetime object]
        * frequency => The frequency at which to do the action.
                      [datetime.timedelta]
    
    Outputs:
        * boolean (whether to do the action), (datetime.datetime)
                                              the last time the action
                                              was carried out.
    
    """
    if type(lastTime) != dt.datetime:
        err.printLog("ERROR:  Wrong Format of datetime")
        return False, False
    timeNow = dt.datetime.now()
    if lastTime > timeNow:
        err.printLog("ERROR:  lastTime more than current time!")
        return False, False

    timeDiff = timeNow - lastTime
    if timeDiff > frequency:
        return True, timeNow
    else:
        return False, lastTime
Beispiel #2
0
def moveCSVData(currData):
    """
   Will move the current data file for permanent storage on the USB pen.

   Outputs:
      * returns new data object (or bad exit code)
   """
    currPath = const.dataFilepath

    # Let this error slide a couple of times
    if not os.path.isfile(currPath):
        const.badPathWarnings += 1
        return currData
    if const.badPathWarnings > 3:
        err.printLog("ERROR: The data file hasn't been created")
        return False

    # Format the date and time to make a filename
    timeNow = tutils.strTimeNow().replace(" ", "_")
    timeNow = tutils.strTimeNow().replace(":", "x")
    timeNow = timeNow.replace("/", "-")
    newPath = "%s/%s.csv" % (const.permDataStoragePath, timeNow)
    carryOn = moveFile(currPath, newPath)
    if carryOn is False:
        return False

    return getCurrData()
Beispiel #3
0
def takePic(test=False):
    """
    Will take a picture using the picamera and the picamera module.
    This involves switching off the grow light, switching on the flash
    finding the correct filename and then taking the pic and storing it
    under that filename.
    """
    # Turn off grow lights and turn on flash
    lUt.switchLight('GrowLight', 'off')
    lUt.switchLight('Flash', 'on')

    # The with statement seems to work fine being called in a loop.
    # Memory leaks will be seen if picam is not properly closed and the
    # code will crash.
    with picam.PiCamera() as cam:
        cam.resolution = (1640, 1232)
        cam.start_preview()
        time.sleep(5)

        fileName = getNewFileNumber(const.imgFolder)
        if test:
            fileName = "testPic.jpg"
            if os.path.isfile(fileName): os.remove(fileName)

        # Actually take the picture
        cam.capture(fileName)
        cam.stop_preview()

    err.printLog("INFO: Taking pic `%s'" % fileName)
    lUt.switchLight('Flash', 'off')
Beispiel #4
0
def initBluetooth(macAddress, port):
    """
    Will initialise the bluetooth module.
    """
    s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
    # no need for a try and except here as errors are already handled
    s.connect((macAddress, port))
    err.printLog("INFO: Bluetooth Connected")
    return s
Beispiel #5
0
def testUSBAddress():
    """
   Will check if the USB drive is recognised and mounted. It must be
   mounted at const.permDataStoragePath.
   """
    if not os.path.isdir(const.permDataStoragePath):
        err.printLog("ERROR: USB drive not mounted at %s" %
                     const.permDataStoragePath)
        return False
    else:
        err.printLog("INFO: USB drive found at %s" % const.permDataStoragePath)
        return True
Beispiel #6
0
def moveFile(currFile, newFile):
    """
   Will move a file to the USB.

   Inputs:
      * currFile => the current file that need moving
      * newFile => the new filepath for the file

   Outputs:
      exit_code
   """
    if not os.path.isfile(currFile):
        msg = "ERROR: Can't find file %s" % currFile
        err.printLog(msg)
        return False

    newFolder = newFile[:newFile.rfind('/')]
    if not os.path.isdir(newFolder):
        msg = "ERROR: Can't find folder %s" % newFolder
        err.printLog(msg)
        return False

    try:
        shutil.move(currFile, newFile)
    except PermissionError as e:
        msg = "ERROR: you don't have permissions to move file "
        msg += "%s to %s" % (currFile, newFile)
        msg += "\n\terror = %s" % (str(e))
        err.printLog(msg)
        return False
    except Exception as e:
        msg = "ERROR: an error occured when trying to move"
        msg += " file %s to %s" % (currFile, newFile)
        msg += "\n\terror = %s" % (str(e))
        err.printLog(msg)
        return False
    finally:
        msg = "ERROR: Unknown in moveFile"
        err.printLog(msg + "\n\targ1 = '%s' arg2 = '%s'" % (currFile, newFile))
        return False

    return True
Beispiel #7
0
def setLastTimes(key, value):
    """
   Will set the lastTimes dictionaries

   Inputs:
      * key => the name of the last time to change
               [str]
      * value => the value to which the last time should be changed.
                 [datetime.datetime]

   Outputs:
      * exit_code
   """
    if type(value) != dt.datetime:
        err.printLog("ERROR: wrong type given for value in lastTimes")
        return False
    if key not in const.allLastTimeVals:
        err.printLog("ERROR: key `%s` not in the allLastTimeVals" % key)
        msg = "\n\tKeys are:\n\t* %s" % "\n\t* ".join(const.allLastTimeVals)
        err.printLog(msg)
        return False

    lastTimes = getLastTimes()
    if lastTimes[key] != value:
        lastTimes[key] = value  # set new val
        # Should be strings for writing
        lastTimes = {
            i: dt.datetime.strftime(lastTimes[i], const.timeFormat)
            for i in lastTimes
        }
        with open(const.lastTimeFilepath, 'w') as f:
            json.dump(lastTimes, f)

    return True
Beispiel #8
0
def getTempHumid():
    """
    Will get the temperature and humidity from the DHT's in the grow tent. 
    """
    # Get readings
    allHumid, allTemp = [], []
    failedPins = []
    for sensor, pin in const.sensorPins['DHT']:
        humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
        if humidity is None or temperature is None:
            failedPins.append((pin, sensor, 'humidity'))
            failedPins.append((pin, sensor, 'temperature'))
        else:
            allHumid.append(humidity)
            allTemp.append(temperature)

    # Report any failed pins
    for pin, sensor, measurement in failedPins:
        msg = "WARNING | SENSOR BROKEN\n"
        msg += "\t Pin = %i\n" % pin
        msg += "\t Type = DHT%s" % (str(sensor))
        msg += "\t Measurement = %s" % measurement
        err.printLog(msg)

    # Do some analysis (exclude outliers and average)
    tMean, hMean = allTemp[0], allHumid[0]
    tBest, hBest = None, None
    if len(allHumid) > 1:
        tStd, hStd = np.std(allHumid) * 2, np.std(allTemp) * 2
        tMean, hMean = np.mean(allTemp), np.mean(allHumid)
        tBest = [t for t in allTemp if tMean - tStd < t < tMean + tStd]
        hBest = [h for h in allHumid if hMean - hStd < h < hMean + hStd]
        tBest = np.mean(tBest)
        hBest = np.mean(hBest)

    humidData = {'all': allHumid, 'mean': hMean, 'real': hBest}
    tempData = {'all': allTemp, 'mean': tMean, 'real': tBest}
    return humidData, tempData
Beispiel #9
0
def getLastTimes(key=False):
    """
   Will read the lastTimes filepath. If it is not there then this will
   return a dictionary with all values set to the current time.

   Inputs:
      * key => the name of the lastTime variable to get

   Outputs:
      * dependent on the value of key, either dict of all lastTimes or
        single lastTime.
   """
    if os.path.isfile(const.lastTimeFilepath):
        with open(const.lastTimeFilepath, 'r') as f:
            try:
                data = json.load(f)
            except json.JSONDecodeError:
                err.printLog(
                    "WARN: Reseting lastTimes dict as json is corrupted.")
                data = {i: strTimeNow() for i in const.allLastTimeVals}

    else:  # defaults to current time
        data = {i: strTimeNow() for i in const.allLastTimeVals}

    for mKey in const.allLastTimeVals:
        if mKey not in data:
            data[mKey] = strTimeNow()

    # If a specific key is requested then return that data
    if key:
        if key in data:
            return dt.datetime.strptime(data[key], const.timeFormat)
        elif key in const.allLastTimeVals:
            timeNow = dt.datetime.now()
            setLastTimes(key, timeNow)
            return timeNow
        else:
            err.printLog(
                "ERROR: key `%s` not available in the lastTimes dictionary" %
                key)
            msg = "\n\tKeys are:\n\t* %s" % "\n\t* ".join(
                const.allLastTimeVals)
            err.printLog(msg)
            return False
    data = {i: dt.datetime.strptime(data[i], const.timeFormat) for i in data}
    return data
Beispiel #10
0
def doEvent(eventName, function, timeDelta, *args):
    """
   Will check if the event `eventName' needs doing (by checking the lastTimes
   dict). If it does need doing the function will be called.

   Inputs:
      * eventName => the name of the event in the lastTimes dictionary
                     [str]
      * function => the action to be carried out if the event needs doing.
                    This function must return a dictionary with one key for
                    an 'exit_code', and one key for 'values'.
                    [func]
      * timeDelta => How often the event needs doing
                    [dt.timedelta]
      * *args => The arguments to pass to the function
                 [tuple]

   Outputs:
      * Exit code (False means quit loop, True is OK)
   """
    carryOn = True
    if eventName not in const.allLastTimeVals:
        msg = "ERROR: Can't find the event called %s" % eventName
        msg += " in the allLastTimeVals list."
        err.printLog(msg)
        return False, False

    allGood, msg = err.typeCheck(timeDelta, dt.timedelta,
                                 "timeDelta (func doEvent)")
    if allGood is False:
        err.printLog("ERROR: %s" % msg)
        return False, False

    # Get the last time the event occured and check if it is time for it again
    lastTime = getLastTimes(eventName)
    doEvent, newLastTime = isTime(lastTime, timeDelta)

    # Actually carry out the func
    carryOn *= bool(newLastTime)
    if doEvent:
        funcDict = function(*args)
    else:
        funcDict = {'exit_code': True}

    allGood, msg = err.typeCheck(funcDict, dict, "funcDict (func doEvent)")
    if allGood is False:
        err.printLog("ERROR: %s" % msg)
        return False, False

    # Handle exit codes
    if 'exit_code' in funcDict:
        carryOn *= funcDict['exit_code']
    # Catch any naughty functions not returning with an exit code
    else:
        msg = "WARN: The function `%s` returns no exit code. Code this up!" % str(
            function)
        err.printLog(msg)

    # Will get the values returned
    if 'values' in funcDict:
        returners = funcDict['values']
    else:
        returners = False

    # Set the new 'lastTime' the event occured
    carryOn *= setLastTimes(eventName, newLastTime)

    return carryOn, returners