<commit_before>#!/usr/bin/env python
# magic_button_.py
"""
Copyright (c) 2015 ContinuumBridge Limited
Written by <NAME>
"""

import sys
import os.path
import time
import json
from twisted.internet import task
from cbcommslib import CbApp, CbClient
from cbconfig import *

configFile          = CB_CONFIG_DIR + "magic_button.config"
CHECK_INTERVAL      = 30
WATCHDOG_INTERVAL   = 40
config = {
          "uuids": [ ],
          "cid": "undefined"
}

class App(CbApp):
    def __init__(self, argv):
        self.state = "stopped"
        self.devices = []
        self.idToName = {} 
        self.buttonStates = {}
        # Super-class init must be called
        CbApp.__init__(self, argv)

    def setState(self, action):
        self.state = action
        msg = {"id": self.id,
               "status": "state",
               "state": self.state}
        self.sendManagerMessage(msg)

    def onConcMessage(self, message):
        self.client.receive(message)

    def checkConnected(self):
        # Called every CHECK_INTERVAL
        now = time.time()
        if self.buttonStates != {}:
            delkeys = []
            for b in self.buttonStates:
                self.cbLog("debug", "checkConnected, buttonStates: " + str(self.buttonStates) + ", b: " + str(b))
                if now - self.buttonStates[b]["connectTime"] > WATCHDOG_INTERVAL:
                    toClient = {"b": b,
                                "p": self.buttonStates[b]["rssi"],
                                "c": False
                               }
                    self.client.send(toClient)
                    delkeys.append(b)
                elif self.buttonStates[b]["rssi_changed"]:
                    toClient = {"b": b,
                                "p": self.buttonStates[b]["rssi"],
                                "c": True
                               }
                    self.client.send(toClient)
                    self.buttonStates[b]["rssi_changed"] = False
                self.cbLog("debug", "checkConnected, buttonStates after del: " + str(self.buttonStates))
            for d in delkeys:
                del self.buttonStates[d]

    def onClientMessage(self, message):
        self.cbLog("debug", "onClientMessage, message: " + str(json.dumps(message, indent=4)))
        global config
        if "uuids" in message:
            config["uuids"] = message["uuids"]
            self.cbLog("debug", "onClientMessage, updated UUIDs: " + str(json.dumps(config, indent=4)))
            try:
                with open(configFile, 'w') as f:
                    json.dump(config, f)
            except Exception as ex:
                self.cbLog("warning", "onClientMessage, could not write to file. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))

    def onAdaptorService(self, message):
        #self.cbLog("debug", "onAdaptorService, message: " + str(message))
        for p in message["service"]:
            if p["characteristic"] == "ble_beacon":
                req = {"id": self.id,
                       "request": "service",
                       "service": [
                                   {"characteristic": "ble_beacon",
                                    "interval": 1.0,
                                    "uuids": config["uuids"]
                                   }
                                  ]
                      }
                self.sendMessage(req, message["id"])

    def onAdaptorData(self, message):
        self.cbLog("debug", "onAdaptorData, message: " + str(json.dumps(message, indent=4)))
        try:
            if self.state != "running":
                self.setState("running")
            if message["characteristic"] == "ble_beacon":
                if message["data"]["uuid"] in config["uuids"]:
                    buttonID = message["data"]["major"]
                    buttonState = message["data"]["minor"] & 0x01
                    if buttonID in self.buttonStates:
                        self.buttonStates[buttonID]["connectTime"] = time.time()
                        if abs(self.buttonStates[buttonID]["rssi"] - message["data"]["rx_power"]) > 4:
                            self.buttonStates[buttonID]["rssi"] = message["data"]["rx_power"]
                            self.buttonStates[buttonID]["rssi_changed"] = True
                    else:
                        self.buttonStates[buttonID] = {
                            "connectTime": time.time(),
                            "rssi":  message["data"]["rx_power"],
                            "rssi_changed": True,
                            "state": -1
                        }
                    if buttonState != self.buttonStates[buttonID]["state"] or self.buttonStates[buttonID]["rssi_changed"]:
                        self.buttonStates[buttonID]["state"] = buttonState
                        toClient = {"b": buttonID,
                                    "s": self.buttonStates[buttonID]["state"],
                                    "p": self.buttonStates[buttonID]["rssi"],
                                    "c": True
                                   }
                        self.client.send(toClient)
                        self.buttonStates[buttonID]["rssi_changed"] = False
        except Exception as ex:
            self.cbLog("warning", "onAdaptorData problem. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))

    def onConfigureMessage(self, managerConfig):
        global config
        try:
            with open(configFile, 'r') as f:
                newConfig = json.load(f)
                self.cbLog("debug", "Read simple_beacon_app.config")
                config.update(newConfig)
        except Exception as ex:
            self.cbLog("warning", "Problem reading magic_button.config. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))
        for c in config:
            if c.lower in ("true", "t", "1"):
                config[c] = True
            elif c.lower in ("false", "f", "0"):
                config[c] = False
        try:
            config["uuids"] = [u.upper() for u in config["uuids"]]
        except Exception as ex:
            self.cbLog("warning", "Problem upper-casing uuids. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))
        self.cbLog("debug", "Config: " + str(json.dumps(config, indent=4)))
        now = time.time()
        for adaptor in managerConfig["adaptors"]:
            adtID = adaptor["id"]
            if adtID not in self.devices:
                # Because managerConfigure may be re-called if devices are added
                name = adaptor["name"]
                friendly_name = adaptor["friendly_name"]
                self.idToName[adtID] = friendly_name.replace(" ", "_")
                self.devices.append(adtID)
        self.client = CbClient(self.id, config["cid"])
        self.client.onClientMessage = self.onClientMessage
        self.client.sendMessage = self.sendMessage
        self.client.cbLog = self.cbLog
        l = task.LoopingCall(self.checkConnected)
        l.start(CHECK_INTERVAL)
        self.setState("starting")

if __name__ == '__main__':
    App(sys.argv)
<commit_msg>Improved reporting of signal strength and loss<commit_after>#!/usr/bin/env python
# magic_button_.py
"""
Copyright (c) 2015 ContinuumBridge Limited
Written by <NAME>
"""

import sys
import os.path
import time
import json
from twisted.internet import task
from cbcommslib import CbApp, CbClient
from cbconfig import *

configFile          = CB_CONFIG_DIR + "magic_button.config"
CHECK_INTERVAL      = 30
WATCHDOG_INTERVAL   = 70
config = {
          "uuids": [ ],
          "cid": "undefined"
}

class App(CbApp):
    def __init__(self, argv):
        self.state = "stopped"
        self.devices = []
        self.idToName = {} 
        self.buttonStates = {}
        # Super-class init must be called
        CbApp.__init__(self, argv)

    def setState(self, action):
        self.state = action
        msg = {"id": self.id,
               "status": "state",
               "state": self.state}
        self.sendManagerMessage(msg)

    def onConcMessage(self, message):
        self.client.receive(message)

    def checkConnected(self):
        # Called every CHECK_INTERVAL
        now = time.time()
        if self.buttonStates != {}:
            delkeys = []
            for b in self.buttonStates:
                #self.cbLog("debug", "checkConnected, buttonStates: " + str(self.buttonStates) + ", b: " + str(b))
                if now - self.buttonStates[b]["connectTime"] > WATCHDOG_INTERVAL:
                    self.buttonStates[b]["rssi"] = -200
                    toClient = {"b": b,
                                "p": self.buttonStates[b]["rssi"],
                                "c": False
                               }
                    self.client.send(toClient)
                    delkeys.append(b)
                #self.cbLog("debug", "checkConnected, buttonStates after del: " + str(self.buttonStates))
            for d in delkeys:
                del self.buttonStates[d]

    def onClientMessage(self, message):
        self.cbLog("debug", "onClientMessage, message: " + str(json.dumps(message, indent=4)))
        global config
        if "uuids" in message:
            config["uuids"] = message["uuids"]
            self.cbLog("debug", "onClientMessage, updated UUIDs: " + str(json.dumps(config, indent=4)))
            try:
                with open(configFile, 'w') as f:
                    json.dump(config, f)
            except Exception as ex:
                self.cbLog("warning", "onClientMessage, could not write to file. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))

    def onAdaptorService(self, message):
        #self.cbLog("debug", "onAdaptorService, message: " + str(message))
        for p in message["service"]:
            if p["characteristic"] == "ble_beacon":
                req = {"id": self.id,
                       "request": "service",
                       "service": [
                                   {"characteristic": "ble_beacon",
                                    "interval": 1.0,
                                    "uuids": config["uuids"]
                                   }
                                  ]
                      }
                self.sendMessage(req, message["id"])

    def onAdaptorData(self, message):
        #self.cbLog("debug", "onAdaptorData, message: " + str(json.dumps(message, indent=4)))
        try:
            if self.state != "running":
                self.setState("running")
            if message["characteristic"] == "ble_beacon":
                if message["data"]["uuid"] in config["uuids"]:
                    changed = False
                    buttonID = message["data"]["major"]
                    buttonState = message["data"]["minor"] & 0x01
                    if buttonID in self.buttonStates:
                        self.buttonStates[buttonID]["connectTime"] = time.time()
                    else:
                        self.buttonStates[buttonID] = {
                            "connectTime": time.time(),
                            "state": -1
                        }
                        self.cbLog("info", "New button: " + str(buttonID))
                    if buttonState != self.buttonStates[buttonID]["state"]:
                        self.buttonStates[buttonID]["state"] = buttonState
                        self.buttonStates[buttonID]["rssi"] = message["data"]["rx_power"]
                        self.buttonStates[buttonID]["rssi_time"] = time.time()
                        changed = True
                    elif abs(self.buttonStates[buttonID]["rssi"] - message["data"]["rx_power"]) > 10:
                        self.buttonStates[buttonID]["rssi"] = message["data"]["rx_power"]
                        self.buttonStates[buttonID]["rssi_time"] = time.time()
                        changed = True
                    elif abs(self.buttonStates[buttonID]["rssi"] - message["data"]["rx_power"]) > 3:
                        if time.time() - self.buttonStates[buttonID]["rssi_time"] > 60 * 15:
                            self.buttonStates[buttonID]["rssi"] = message["data"]["rx_power"]
                            self.buttonStates[buttonID]["rssi_time"] = time.time()
                            changed = True
                    if changed:
                        toClient = {"b": buttonID,
                                    "s": self.buttonStates[buttonID]["state"],
                                    "p": self.buttonStates[buttonID]["rssi"],
                                    "c": True
                                   }
                        self.client.send(toClient)
                        self.cbLog("debug", "Sent to client: " + str(json.dumps(toClient, indent=4)))
        except Exception as ex:
            self.cbLog("warning", "onAdaptorData problem. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))

    def onConfigureMessage(self, managerConfig):
        global config
        try:
            with open(configFile, 'r') as f:
                newConfig = json.load(f)
                self.cbLog("debug", "Read simple_beacon_app.config")
                config.update(newConfig)
        except Exception as ex:
            self.cbLog("warning", "Problem reading magic_button.config. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))
        for c in config:
            if c.lower in ("true", "t", "1"):
                config[c] = True
            elif c.lower in ("false", "f", "0"):
                config[c] = False
        try:
            config["uuids"] = [u.upper() for u in config["uuids"]]
        except Exception as ex:
            self.cbLog("warning", "Problem upper-casing uuids. Type: " + str(type(ex)) + ", exception: " +  str(ex.args))
        self.cbLog("debug", "Config: " + str(json.dumps(config, indent=4)))
        now = time.time()
        for adaptor in managerConfig["adaptors"]:
            adtID = adaptor["id"]
            if adtID not in self.devices:
                # Because managerConfigure may be re-called if devices are added
                name = adaptor["name"]
                friendly_name = adaptor["friendly_name"]
                self.idToName[adtID] = friendly_name.replace(" ", "_")
                self.devices.append(adtID)
        self.client = CbClient(self.id, config["cid"], 3)
        self.client.onClientMessage = self.onClientMessage
        self.client.sendMessage = self.sendMessage
        self.client.cbLog = self.cbLog
        l = task.LoopingCall(self.checkConnected)
        l.start(CHECK_INTERVAL)
        self.setState("starting")

if __name__ == '__main__':
    App(sys.argv)

{'fraction_non_alphanumeric': 0.12725791117750918, 'fraction_numerical': 0.0035990764633980713, 'mean_word_length': 1.579611140304782, 'pattern_counts': {'":': 51, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5170767', 'n_tokens_mistral': 4119, 'n_tokens_neox': 3970, 'n_words': 832}