<commit_before>#!/usr/bin/env python

# http://www.gavinj.net/2012/06/building-python-daemon-process.html

import time
import logging
import serial
import re

# third party libs
from daemon import runner
from Monitor import Monitor

HEART_BEAT = 1


class App(Monitor):

    def __init__(self, *args, **kwargs):
        
        Monitor.__init__(self, *args, **kwargs)

        self.port = '/dev/ttyUSB0'
        # stty settings
        self.stty = "5:0:8be:0:0:0:0:0:0:a" + ":0" * 26

    def communicate(self, command):
        '''communicate with wattson energy monitor'''

        self.logger.debug('sending commands %s' % command)
        ser = self.connection
        ser.flush()
        ser.flushInput()
        ser.flushOutput()
        ser.write(command + "\r")

        time.sleep(1)
        
        logger.debug("waiting for return data")

        for i in range(5):
            r = []
            while ser.inWaiting() > 0:
                r.append(ser.read(1))
            if len(r) > 0:
                break
            time.sleep(0.1)

        self.logger.debug("received %i bytes after %i tries" %
                     (len(r), i))

        if len(r) == 0:
            return None

        # skip first character
        r = ''.join(r[1:])
        # remove everything after line break
        r = re.sub("\r(.*|$)", "", r)
        # remove new-line
        r = r.rstrip()
        if len(r) == 0:
            return None
        return r
        
    def setup(self):

        Monitor.setup(self)
        self.logger.debug("wattson: port=%s" % self.port)
        
        # 19200, 8N1
        # 8 data bits, no parity bit, 1 stop bit
        self.connection = serial.Serial(
            port=self.port,
            baudrate=19200,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            bytesize=serial.EIGHTBITS)

        self.connection.open()
        assert self.connection.isOpen()

        data = self.communicate("nows")

        self.logger.info("connected to wattson device %s" % data)

    def monitor(self):
        '''
        '''
        grid_status, solar_status = "ok", "ok"

        # first command always fails
        solar_power = self.communicate("noww")
        solar_power = self.communicate("noww")
        if solar_power is None:
            solar_status = "fail"
            solar_power = 0
        elif len(solar_power) != 4:
            logger.warning(
                "malformed grid power: %s" % list(solar_power))
            solar_status = "fail"
            solar_power = 0
        else:
            solar_power = int(solar_power, 16)

        # get current energy usage in watts
        grid_power = self.communicate("nowp")
        if grid_power is None:
            grid_status = "fail"
            grid_power = 0
        elif len(grid_power) != 4:
            logger.warning(
                "malformed grid power: %s" % list(grid_power))
            grid_status = "fail"
            grid_power = None
        else:
            grid_power = int(grid_power, 16)

        self.logger.debug(
            "acquired values: grid=%s, solar=%s" %
            (grid_power, solar_power))

        self.logger.debug(
            "status: grid=%s, solar=%s" %
            (grid_status, solar_status))

        values = {'Wattson.Power.Grid': grid_power,
                  'Wattson.Power.Solar': solar_power}

        return values

logger = logging.getLogger("DaemonLog")
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
    "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.FileHandler("/mnt/ramdisk/wattson.log")
handler.setFormatter(formatter)
logger.addHandler(handler)
app = App(logger=logger, heart_beat=HEART_BEAT)

# app.run()

daemon_runner = runner.DaemonRunner(app)
# This ensures that the logger file handle does not get closed during
# daemonization
daemon_runner.daemon_context.files_preserve = [handler.stream]
daemon_runner.do_action()<commit_msg>no exception on malformed power<commit_after>#!/usr/bin/env python

# http://www.gavinj.net/2012/06/building-python-daemon-process.html

import time
import logging
import serial
import re

# third party libs
from daemon import runner
from Monitor import Monitor

HEART_BEAT = 1


class App(Monitor):

    def __init__(self, *args, **kwargs):
        
        Monitor.__init__(self, *args, **kwargs)

        self.port = '/dev/ttyUSB0'
        # stty settings
        self.stty = "5:0:8be:0:0:0:0:0:0:a" + ":0" * 26

    def communicate(self, command):
        '''communicate with wattson energy monitor'''

        self.logger.debug('sending commands %s' % command)
        ser = self.connection
        ser.flush()
        ser.flushInput()
        ser.flushOutput()
        ser.write(command + "\r")

        time.sleep(1)
        
        logger.debug("waiting for return data")

        for i in range(5):
            r = []
            while ser.inWaiting() > 0:
                r.append(ser.read(1))
            if len(r) > 0:
                break
            time.sleep(0.1)

        self.logger.debug("received %i bytes after %i tries" %
                     (len(r), i))

        if len(r) == 0:
            return None

        # skip first character
        r = ''.join(r[1:])
        # remove everything after line break
        r = re.sub("\r(.*|$)", "", r)
        # remove new-line
        r = r.rstrip()
        if len(r) == 0:
            return None
        return r
        
    def setup(self):

        Monitor.setup(self)
        self.logger.debug("wattson: port=%s" % self.port)
        
        # 19200, 8N1
        # 8 data bits, no parity bit, 1 stop bit
        self.connection = serial.Serial(
            port=self.port,
            baudrate=19200,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            bytesize=serial.EIGHTBITS)

        self.connection.open()
        assert self.connection.isOpen()

        data = self.communicate("nows")

        self.logger.info("connected to wattson device %s" % data)

    def monitor(self):
        '''
        '''
        grid_status, solar_status = "ok", "ok"

        # first command always fails
        solar_power = self.communicate("noww")
        solar_power = self.communicate("noww")
        if solar_power is None:
            solar_status = "fail"
            solar_power = 0
        elif len(solar_power) != 4:
            logger.warning(
                "malformed grid power: %s" % list(solar_power))
            solar_status = "fail"
            solar_power = 0
        else:
            solar_power = int(solar_power, 16)

        # get current energy usage in watts
        grid_power = self.communicate("nowp")
        if grid_power is None:
            grid_status = "fail"
            grid_power = 0
        elif len(grid_power) != 4:
            logger.warning(
                "malformed grid power: %s" % list(grid_power))
            grid_status = "fail"
            grid_power = None
        else:
            grid_power = int(grid_power, 16)

        self.logger.debug(
            "acquired values: grid=%s, solar=%s" %
            (grid_power, solar_power))

        self.logger.debug(
            "status: grid=%s, solar=%s" %
            (grid_status, solar_status))

        values = {'Wattson.Power.Grid': grid_power,
                  'Wattson.Power.Solar': solar_power}

        return values

logger = logging.getLogger("DaemonLog")
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
    "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.FileHandler("/mnt/ramdisk/wattson.log")
handler.setFormatter(formatter)
logger.addHandler(handler)
app = App(logger=logger, heart_beat=HEART_BEAT)

app.run()

daemon_runner = runner.DaemonRunner(app)
# This ensures that the logger file handle does not get closed during
# daemonization
daemon_runner.daemon_context.files_preserve = [handler.stream]
daemon_runner.do_action()
{'fraction_non_alphanumeric': 0.11731493099121706, 'fraction_numerical': 0.013299874529485571, 'mean_word_length': 1.9326710816777042, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2747573', 'n_tokens_mistral': 2531, 'n_tokens_neox': 2414, 'n_words': 559}