diff --git a/Docker/Dockerfile b/Docker/Dockerfile index 3b76174..ef55938 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -6,11 +6,8 @@ LABEL version="1.0" WORKDIR /app COPY . /app ENV PYTHONPATH=/app/src/python +RUN pip install --upgrade pip RUN pip install -r requirements.txt -RUN echo "http://dl-8.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories -RUN apk --no-cache --update-cache add gcc python-dev build-base -RUN ln -s /usr/include/locale.h /usr/include/xlocale.h -RUN pip install --no-cache-dir numpy RUN rm -rf /var/cache/apk CMD ["/app/src/bin/tHome-eagle.py", "-c", "/app/src/conf"] diff --git a/Docker/src/bin/acurite-redirect.sh b/Docker/src/bin/acurite-redirect.sh deleted file mode 100755 index 805aa7e..0000000 --- a/Docker/src/bin/acurite-redirect.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# This script configures the eb/ip tables rules to redirect traffic -# from the bridge to a different port on the local machine. It gets -# run by adding this line to /etc/network/interfaces -# -# pre-up /home/ted/proj/tHome/bin/acurite-redirect.sh -# - -# Redirect traffic on the bridge to port 22041 which must match the port -# specified in tHome/conf/acurite.py. -PORT=22041 - -# Tell the bridge to push the packet to iptables. -ebtables -t broute -A BROUTING -p IPv4 --ip-protocol 6 --ip-destination-port 80 -j redirect --redirect-target ACCEPT - -# Redirect the packet to the other port. -iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j REDIRECT --to-port $PORT diff --git a/Docker/src/bin/tHome-acurite.py b/Docker/src/bin/tHome-acurite.py deleted file mode 100755 index 69b4f4a..0000000 --- a/Docker/src/bin/tHome-acurite.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python - -#=========================================================================== -# -# Eagle posting server -# -#=========================================================================== - -__doc__ = """ -Starts a small web server to read packets sent from an Acurite Bridgek. - -The Acurite must be redirected to post messages to server instead of -it's main server. This assumes the Bridge is connected to a raspberry -pi using a USB network adaptor with it's network bridged to the main -network. NOTE: The last port number in the iptables command must -match the port configured in conf/acurite.py for the acurite web -server. - -ebtables -t broute -A BROUTING -p IPv4 --ip-protocol 6 --ip-destination-port 80 -j redirect --redirect-target ACCEPT -iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j REDIRECT --to-port 22041 - -Scripts uses the tHome.acurite package to decode the bridge posts and -converts them to JSON dictionaries which get sent out as MQTT -messages. -""" - -import argparse -import bottle as B -import sys -import json -import tHome as T - -#=========================================================================== -@B.post( '/' ) -@B.post( '/messages/' ) -def bridge_post(): - content = B.request.body.read( B.request.content_length ) - - log.info( "Read: %s" % content ) - - # Convert the line to messages. Returns a list of tuples of - # ( topic, dict ). - msgs = T.acurite.cmdLine.process( cfg, content, sensorMap ) - - # Send the messages out. - for topic, data in msgs: - log.info( "Publish: %s: %s" % ( topic, data ) ) - - payload = json.dumps( data ) - client.publish( topic, payload ) - - # Standard acurite web site reply - found by watching traffic to - # the acurite web site. - return { "success" : 1, "checkversion" : "126" } - -#=========================================================================== -# -# Main applications script -# -#=========================================================================== - -p = argparse.ArgumentParser( prog=sys.argv[0], - description="T-Home Acurite Server" ) -p.add_argument( "-c", "--configDir", metavar="configDir", - default="/etc/tHome", - help="Configuration file directory." ) -p.add_argument( "-l", "--log", metavar="logFile", - default=None, help="Logging file to use. Input 'stdout' " - "to log to the screen." ) -c = p.parse_args( sys.argv[1:] ) - -# Parse the eagle config file. -cfg = T.acurite.config.parse( c.configDir ) -log = T.acurite.config.log( cfg, c.log ) - -# Create a sensor map from the configuration file. -sensorMap = {} -for s in cfg.sensors: - sensorMap[s.id] = s - -# Create the MQTT client and connect it to the broker. -client = T.broker.connect( c.configDir, log ) - -# Start the MQTT as a background thread. This way we can run the web -# server as the main thread here. -client.loop_start() - -log.info( "Starting web server at port %d" % cfg.httpPort ) -B.run( host='0.0.0.0', port=cfg.httpPort, quiet=True ) - diff --git a/Docker/src/bin/tHome-sma.py b/Docker/src/bin/tHome-sma.py deleted file mode 100755 index d889c2f..0000000 --- a/Docker/src/bin/tHome-sma.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -import sys -import tHome.sma - -tHome.sma.cmdLine.run( sys.argv ) diff --git a/Docker/src/bin/tHome-thermostat.py b/Docker/src/bin/tHome-thermostat.py deleted file mode 100755 index 52cab70..0000000 --- a/Docker/src/bin/tHome-thermostat.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python - -#=========================================================================== -# -# Radio thermostats reader -# -#=========================================================================== - -import argparse -import sys -import time -import json -import tHome as T - -#=========================================================================== - -#=========================================================================== -# -# Main applications script -# -#=========================================================================== - -p = argparse.ArgumentParser( prog=sys.argv[0], - description="T-Home Thermostats" ) -p.add_argument( "-c", "--configDir", metavar="configDir", - default="/etc/tHome", - help="Configuration file directory." ) -p.add_argument( "-l", "--log", metavar="logFile", - default=None, help="Logging file to use. Input 'stdout' " - "to log to the screen." ) -c = p.parse_args( sys.argv[1:] ) - -# Parse the thermostat config file. -cfg = T.thermostat.config.parse( c.configDir ) -log = T.thermostat.config.log( cfg, c.log ) - -# Create the MQTT client and connect it to the broker. -client = T.broker.connect( c.configDir, log ) - -# Handle set messages being set to the thermostats. -def on_message( client, userData, msg ): - for t in cfg.thermostats: - if mqtt.topic_matches_sub( t.mqttSetTopic, msg.topic ): - t.processSet( client, msg ) - return - -client.on_message = on_message - -# Subscribe to the set messages. -for t in cfg.thermostats: - print t - client.subscribe( t.mqttSetTopic ) - -# Start the MQTT as a background thread. This way we can run the web -# server as the main thread here. -client.loop_start() - -while True: - t0 = time.time() - for t in cfg.thermostats: - try: - # Poll the thermostat for status. - t.status() - - # Publish any messages. - msgs = t.messages() - for topic, msg in msgs: - payload = json.dumps( msg ) - client.publish( topic, payload ) - - except Exception as e: - # This prints a stack trace which is more than we really want. - #log.exception( "Error getting thermostat status." ) - log.error( "Error getting thermostat status: " + str( e ) ) - - dt = time.time() - t0 - delay = max( cfg.pollTime, cfg.pollTime-dt ) - time.sleep( delay ) - - diff --git a/Docker/src/bin/tHome-wug.py b/Docker/src/bin/tHome-wug.py deleted file mode 100755 index 834c298..0000000 --- a/Docker/src/bin/tHome-wug.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -import sys -import tHome.weatherUnderground - -tHome.weatherUnderground.cmdLine.run( sys.argv ) diff --git a/Docker/src/conf/acurite.py b/Docker/src/conf/acurite.py deleted file mode 100644 index 406ca6b..0000000 --- a/Docker/src/conf/acurite.py +++ /dev/null @@ -1,63 +0,0 @@ -#=========================================================================== -# -# Port to use for the web server. Configure the ebtables/iptables -# rules to redirect Acurite Bridge posts to this port. -# -# NOTE: The port specified in the script tHome/bin/tHome-acurite.py -# must match this port. If you change one, change the other. -# -#=========================================================================== -httpPort = 22041 - -#=========================================================================== -# -# Acurite sensor configuration -# -#=========================================================================== -import tHome.acurite as A - -# Sensors list. -# -# ID is the Acurite sensor ID (easiest to find by running the message -# debugger and watching them come through). -sensors = [ - # sensor ID, location label, optional args - A.Sensor( "08260", "Garage" ), - A.Sensor( "09096", "Kitchen" ), - A.Sensor( "00414", "Backyard" ), - A.Sensor( "24C86E0449A0", "Bridge" ), - A.Sensor( "05250", "Courtyard", humidity=False ), - A.Sensor( "16039", "Rec Room", humidity=False ), - A.Sensor( "02717", "Front Bedroom", humidity=False ), - A.Sensor( "05125", "Den", humidity=False ), - A.Sensor( "08628", "Garage 2", humidity=False ), - A.Sensor( "09338", "Side Bedroom", humidity=False ), - A.Sensor( "01948", "Master Closet", humidity=False ), - A.Sensor( "15116", "Attic", humidity=False ), - A.Sensor( "05450", "Master Bath", humidity=False ), - ] - -#=========================================================================== -# -# MQTT Topics. Each requires one %s in the topic which will be -# replaced by the location string from the sensor list above. -# -#=========================================================================== -mqttBattery = "power/battery/%s" -mqttRssi = "radio/%s" -mqttHumidity = "env/humidity/%s" -mqttTemp = "env/temp/%s" -mqttWindSpeed = "env/wind/speed/%s" -mqttWindDir = "env/wind/direction/%s" -mqttBarometer = "env/barometer/%s" -mqttRain = "env/rain/%s" - -#=========================================================================== -# -# Logging configuration -# -#=========================================================================== -logFile = '/var/log/tHome/acurite.log' -logLevel = 40 - - diff --git a/Docker/src/conf/sma.py b/Docker/src/conf/sma.py deleted file mode 100644 index b6c7145..0000000 --- a/Docker/src/conf/sma.py +++ /dev/null @@ -1,51 +0,0 @@ -#=========================================================================== -# -# SMA WebConnect solar inverter configuration -# -#=========================================================================== -# Lat and lon of the installation location used to compute rise/set -# times for the sun. Time pad is the time to offset from the rise/set -# time in seconds at which to start polling the inverter. -lat = 34.466426 -lon = -118.521923 -timePad = 600 # 10 minutes before/after sunrise/set - -# WebConnect module location. -host = '192.168.1.14' -port = 9522 -group = 'USER' -password = '0000' - -#=========================================================================== -# -# Reporting configuration -# -#=========================================================================== -# Polling interval in seconds for each of the reports. Use zero -# to disable a report. -pollPower = 15 -pollEnergy = 600 -pollFull = 0 - -#=========================================================================== -# -# MQTT topic names -# -#=========================================================================== -# Meter reading topic (reports daily energy total in kWh) -mqttEnergy = 'power/solar/Home/energy' - -# Instantaneous power usage topic (reports power usage in W) -mqttPower = 'power/solar/Home/power' - -# Detailed data from full report (somewhat slow to run) -mqttFull = 'power/solar/Home/detail' - -#=========================================================================== -# -# Logging configuration -# -#=========================================================================== -logFile = '/var/log/tHome/sma.log' -logLevel = 40 - diff --git a/Docker/src/conf/thermostat.py b/Docker/src/conf/thermostat.py deleted file mode 100644 index 303bc50..0000000 --- a/Docker/src/conf/thermostat.py +++ /dev/null @@ -1,45 +0,0 @@ -#=========================================================================== -# -# Radio thermostat device configuration -# -#=========================================================================== -# Time in seconds to poll the thermostat -pollTime = 60 - -# Thermostats to poll. Keys are: -# host thermostat IP address -# label label to use in logs and messages. -# mqttTempTopic MQTT topic to publish current temp messages to. -# mqttModeTopic MQTT topic to publish mode changes to. -# mqttStateTopic MQTT topic to publish state (on/off) changes to. -# mqttSetTopic MQTT topic to subscribe to read requests to change -# the thermostat. -# -thermostats = [ - { - 'host' : '192.168.1.15', - 'label' : 'Downstairs', - 'mqttTempTopic' : 'env/temp/Living Room', - 'mqttModeTopic' : 'hvac/Living Room/mode', - 'mqttStateTopic' : 'hvac/Living Room/state', - 'mqttSetTopic' : 'hvac/Living Room/set/+', - }, - { - 'host' : '192.168.1.16', - 'label' : 'Upstairs', - 'mqttTempTopic' : 'env/temp/Master Bedroom', - 'mqttModeTopic' : 'hvac/Master Bedroom/mode', - 'mqttStateTopic' : 'hvac/Master Bedroom/state', - 'mqttSetTopic' : 'hvac/Master Bedroom/set/+', - }, - ] - -#=========================================================================== -# -# Logging configuration -# -#=========================================================================== -logFile = '/var/log/tHome/thermostat.log' -logLevel = 40 - - diff --git a/Docker/src/conf/weatherUnderground.py b/Docker/src/conf/weatherUnderground.py deleted file mode 100644 index 7ada9f5..0000000 --- a/Docker/src/conf/weatherUnderground.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -#=========================================================================== -# -# Weather underground configuration -# -#=========================================================================== - -# PWD upload URL and log in information. See this url for details: -# http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol -uploadUrl = "http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php" - -id = os.environ[ "THOME_WUG_STATION" ] -password = os.environ[ "THOME_WUG_PASSWORD" ] - -# Upload interval in seconds. WUG doesn't really support high rate -# data so 1-2 minutes is fine. -poll = 180 - -# Maximum expected sensor input rate. System will store poll/maxRate -# values in a circular buffer and average the last set of values to up -# load. So if poll is 120 and maxRate is 10, a buffer with 12 values -# will be created. As data is received, it will be inserted into the -# buffer and the last n values (up to 12) since the last upload will -# be averaged to get the value to upload. Some values like wind gust -# will use the maximum value in the interval instead of the average. -# Rain values are accumulated, not averaged. -maxRate = 10 - -# Number of floating point digits to the right of the decimal to round -# values to before uploading them. -digits = 2 - -#=========================================================================== -# -# MQTT topic names. These are the sensors to upload. -# -#=========================================================================== -# List of temperature topics to report as outdoor temperatures. -mqttTemp = [ - "env/temp/Backyard", - "env/temp/Courtyard", - ] - -mqttHumidity = 'env/humidity/Backyard' -mqttBarometer = 'env/barometer/Bridge' -mqttRain = 'env/rain/Backyard' -mqttWindSpeed = 'env/wind/speed/Backyard' -mqttWindDir = 'env/wind/direction/Backyard' - -#=========================================================================== -# -# Logging configuration -# -#=========================================================================== -logFile = '/var/log/tHome/weatherUnderground.log' -logLevel = 20 - diff --git a/Docker/src/init.d/README.txt b/Docker/src/init.d/README.txt deleted file mode 100644 index 95962f3..0000000 --- a/Docker/src/init.d/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -SCRIPT=tHome-thermostat - -sudo cp $SCRIPT /etc/init.d/ -cd /etc/init.d/ -ll $SCRIPT -sudo chmod 755 $SCRIPT -sudo update-rc.d $SCRIPT defaults -sudo update-rc.d $SCRIPT enable -sudo service $SCRIPT start diff --git a/Docker/src/init.d/tHome-thermostat b/Docker/src/init.d/tHome-thermostat deleted file mode 100644 index 5a96280..0000000 --- a/Docker/src/init.d/tHome-thermostat +++ /dev/null @@ -1,160 +0,0 @@ -#! /bin/sh -### BEGIN INIT INFO -# Provides: tHome-thermostat -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Thermostat reader to ZMQ messages. -# Description: This file should be used to construct scripts to be -# placed in /etc/init.d. -### END INIT INFO - -# Author: Foo Bar -# -# Please remove the "Author" lines above and replace them -# with your own name if you copy and modify this script. - -# Do NOT "set -e" - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="Thermostat reader" -NAME=tHome-thermostat -DAEMON=/home/ted/proj/tHome/bin/tHome-thermostats.py -DAEMON_ARGS="-c /home/ted/conf" -PIDFILE=/var/run/$NAME.pid -SCRIPTNAME=/etc/init.d/$NAME -PYTHONPATH=/home/ted/python - -# Exit if the package is not installed -[ -x "$DAEMON" ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/$NAME ] && . /etc/default/$NAME - -# Load the VERBOSE setting and other rcS variables -. /lib/init/vars.sh - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.2-14) to ensure that this file is present -# and status_of_proc is working. -. /lib/lsb/init-functions - -# -# Function that starts the daemon/service -# -do_start() -{ - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - start-stop-daemon --start --background -c ted --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ - || return 1 - start-stop-daemon --start --background -c ted --quiet --pidfile $PIDFILE --exec $DAEMON -- \ - $DAEMON_ARGS \ - || return 2 - # Add code here, if necessary, that waits for the process to be ready - # to handle requests from services started subsequently which depend - # on this one. As a last resort, sleep for some time. -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME - RETVAL="$?" - [ "$RETVAL" = 2 ] && return 2 - # Wait for children to finish too if this is a daemon that forks - # and if the daemon is only ever run from this initscript. - # If the above conditions are not satisfied then add some other code - # that waits for the process to drop all resources that could be - # needed by services started subsequently. A last resort is to - # sleep for some time. - start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON - [ "$?" = 2 ] && return 2 - # Many daemons don't delete their pidfiles when they exit. - rm -f $PIDFILE - return "$RETVAL" -} - -# -# Function that sends a SIGHUP to the daemon/service -# -do_reload() { - # - # If the daemon can reload its configuration without - # restarting (for example, when it is sent a SIGHUP), - # then implement that here. - # - start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME - return 0 -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; - #reload|force-reload) - # - # If do_reload() is not implemented then leave this commented out - # and leave 'force-reload' as an alias for 'restart'. - # - #log_daemon_msg "Reloading $DESC" "$NAME" - #do_reload - #log_end_msg $? - #;; - restart|force-reload) - # - # If the "reload" option is implemented then remove the - # 'force-reload' alias - # - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 - echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 - exit 3 - ;; -esac - -: diff --git a/Docker/src/python/tHome/__init__.py b/Docker/src/python/tHome/__init__.py index e729df3..46c0457 100644 --- a/Docker/src/python/tHome/__init__.py +++ b/Docker/src/python/tHome/__init__.py @@ -9,13 +9,9 @@ __doc__ = """T-Home Python package #=========================================================================== -from . import acurite from . import broker from . import eagle -from . import sma -from . import thermostat from . import util -from . import weatherUnderground #=========================================================================== diff --git a/Docker/src/python/tHome/acurite/Sensor.py b/Docker/src/python/tHome/acurite/Sensor.py deleted file mode 100644 index e086514..0000000 --- a/Docker/src/python/tHome/acurite/Sensor.py +++ /dev/null @@ -1,30 +0,0 @@ -#=========================================================================== -# -# Sensor configuration class -# -#=========================================================================== - -#=========================================================================== -class Sensor: - """Sensor msg processer. - - Set humidity to False for temp only sensors to clear the humidity - field. The bridge reports humidity of 16% for these sensors which - is incorrrect. - """ - def __init__( self, id, location, humidity=True ): - self.id = id - self.location = location - self.hasHumidity = humidity - - #------------------------------------------------------------------------ - def process( self, msg ): - assert( self.id == msg.id ) - msg.location = self.location - - # Remove the humidity attribute if the sensor doesn't suppor it. - if not self.hasHumidity and hasattr( msg, "humidity" ): - del msg.humidity - -#=========================================================================== - diff --git a/Docker/src/python/tHome/acurite/__init__.py b/Docker/src/python/tHome/acurite/__init__.py deleted file mode 100644 index be7ccf4..0000000 --- a/Docker/src/python/tHome/acurite/__init__.py +++ /dev/null @@ -1,72 +0,0 @@ -#=========================================================================== -# -# Acurite weather station package. -# -#=========================================================================== - -__doc__ = """T-Home Acurite weather station package. - -Used to intercept Acurite post commands from an Acurite bridge being -posted to the Acurite web sites. The bridge reads radio traffic from -the sensors and posts them. - -This package assumes the code is run on a system in-line with the -bridge. See: http://www.bobshome.net/weather/ for details. - -Designed for use w/ a Raspberry Pi. Use a USB network adaptor and -plug the bridge into the adaptor. Run the code on the pi with the USB -network adaptor set up as a bridge to the regular network. - -On the PI, install bridge and TCP monitoring utilities: - - apt-get install bridge-utils tcpdump tcpflow - -Then edit /etc/network/interfaces to configure the USB network as a -bridge to the main network. - --------------- -auto lo - -iface lo inet loopback -iface eth0 inet dhcp - -allow-hotplug wlan0 -iface wlan0 inet manual -wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf -iface default inet dhcp - -auto eth1 br0 -iface br0 inet dhcp -iface eth1 inet manual - -bridge_ports eth0 eth1 --------------- - -The restart the network: - - sudo service networking restart - -To access the data, use tcpflow (see bin/acurite-read.sh for this -script) to intercept data from the USB link and pass it to the script. - --------------- -#!/bin/sh - -SCRIPT=$HOME/tHome/bin/acurite-send.py -LOG=/var/log/tHome/acurite-send.log - -(/usr/bin/tcpflow -c -i eth1 -s tcp dst port 80 | $SCRIPT) 2>> $LOG & --------------- - -""" - -#=========================================================================== -from . import cmdLine -from . import config -from .decode import decode -from . import mqtt -from .Sensor import Sensor - -#=========================================================================== - - diff --git a/Docker/src/python/tHome/acurite/cmdLine.py b/Docker/src/python/tHome/acurite/cmdLine.py deleted file mode 100644 index af43d56..0000000 --- a/Docker/src/python/tHome/acurite/cmdLine.py +++ /dev/null @@ -1,68 +0,0 @@ -#=========================================================================== -# -# Acurite bridge parser -# -#=========================================================================== -import argparse -import json -import sys -from .. import broker -from . import config -from .decode import decode -from . import mqtt - - -#=========================================================================== -def process( config, text, sensorMap ): - idx = text.find( "id=" ) - if idx == -1: - return [] - - # Parse the data from the HTTP command. - data = decode( text[idx:], sensorMap ) - if not data: - return [] - - # Convert to a list of MQTT (topic, payload) tuples. - return mqtt.convert( config, data ) - -#=========================================================================== -def run( args, input=sys.stdin ): - """DEPRECATED - - This function is used when intercepting bridge traffic. The new - way redirects bridge traffic which bin/tHome-acurite.py handles so - this function isn't needed any more. - """ - - p = argparse.ArgumentParser( prog=args[0], - description="Acurite decoder" ) - p.add_argument( "-c", "--configDir", metavar="configDir", - default="/var/config/tHome", - help="T-Home configuration directory." ) - p.add_argument( "-l", "--log", metavar="logFile", - default=None, help="Logging file to use. Input 'stdout' " - "to log to the screen." ) - c = p.parse_args( args[1:] ) - - # Parse the acurite config file. - cfg = config.parse( c.configDir ) - log = config.log( cfg, c.log ) - - sensorMap = {} - for s in cfg.sensors: - sensorMap[s.id] = s - - # Create the MQTT client and connect it to the broker. - client = broker.connect( c.configDir, log ) - - while True: - line = sys.stdin.readline() - msgs = process( cfg, line, sensorMap ) - - for topic, data in msgs: - log.info( "Publish: %s: %s" % ( topic, payload ) ) - payload = json.dumps( data ) - client.publish( topic, payload ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/acurite/config.py b/Docker/src/python/tHome/acurite/config.py deleted file mode 100644 index aa2df14..0000000 --- a/Docker/src/python/tHome/acurite/config.py +++ /dev/null @@ -1,46 +0,0 @@ -#=========================================================================== -# -# Config file -# -#=========================================================================== - -__doc__ = """Config file parsing. -""" - -from .. import util -from ..util import config as C - -#=========================================================================== - -# Config file section name and defaults. -configEntries = [ - # ( name, converter function, default value ) - C.Entry( "logFile", util.path.expand ), - C.Entry( "logLevel", int, 20 ), # INFO - C.Entry( "sensors", list ), - C.Entry( "mqttBattery", str ), - C.Entry( "mqttRssi", str ), - C.Entry( "mqttHumidity", str ), - C.Entry( "mqttTemp", str ), - C.Entry( "mqttWindSpeed", str ), - C.Entry( "mqttWindDir", str ), - C.Entry( "mqttBarometer", str ), - C.Entry( "mqttRain", str ), - ] - -#=========================================================================== -def parse( configDir, configFile='acurite.py' ): - m = C.readAndCheck( configDir, configFile, configEntries ) - return m - -#=========================================================================== -def log( config, logFile=None ): - if not logFile: - logFile = config.logFile - - return util.log.get( "acurite", config.logLevel, logFile ) - -#=========================================================================== - - - diff --git a/Docker/src/python/tHome/acurite/decode.py b/Docker/src/python/tHome/acurite/decode.py deleted file mode 100644 index ed51faa..0000000 --- a/Docker/src/python/tHome/acurite/decode.py +++ /dev/null @@ -1,172 +0,0 @@ -#=========================================================================== -# -# Acurite sensor data class -# -#=========================================================================== -import StringIO -import time -from ..util import Data - -#------------------------------------------------------------------------ -windMap = { - '5' : 0, - '7' : 22.5, - '3' : 45, - '1' : 67.5, - '9' : 90, - 'B' : 112.5, - 'F' : 135, - 'D' : 157.5, - 'C' : 180, - 'E' : 202.5, - 'A' : 225, - '8' : 247.5, - '0' : 270, - '2' : 292.5, - '6' : 315, - '4' : 337.5, - } - -#------------------------------------------------------------------------ -batteryMap = { - "normal" : 1.0, - "low" : 0.1, - } - -#=========================================================================== -def decode( text, sensorMap ): - """Decode a sensor post from the Acurite bridge. - - Input is a line of text sent by the bridge to the Acurite server. - Return valeue is a tHome.util.Data object (dict) with the parsed - values. - """ - # Skip lines that aren't the sensor information. - idx = text.find( "id=" ) - if idx == -1: - return - - text = text[idx:] - - # Split the input into fields. - elems = text.split( "&" ) - - # Get the key/value pairs for each element. - items = {} - for e in elems: - k, v = e.split( "=" ) - items[k] = v - - # Create an empty data object (dict) to store the results. - data = Data() - - # No time field in the data - record the current time as the time - # stamp. - data.time = time.time() - - # Call the handler function for each element. - for k, v in items.iteritems(): - func = handlers.get( k, None ) - if func: - func( data, items, k, v ) - - # Use the sensor map to process the data. This primarily sets a - # location label given the sensor ID field. - s = sensorMap.get( data.id, None ) - if s: - s.process( data ) - else: - data.location = "Unknown" - - return data - -#=========================================================================== -def _readSensor( data, items, key, value ): - data.id = value - -#=========================================================================== -def _readPressure( data, items, key, value ): - if value != "pressure": - return - - # Convert hex strings to integer values - c1 = int( items["C1"], 16 ) - c2 = int( items["C2"], 16 ) - c3 = int( items["C3"], 16 ) - c4 = int( items["C4"], 16 ) - c5 = int( items["C5"], 16 ) - c6 = int( items["C6"], 16 ) - c7 = int( items["C7"], 16 ) - a = int( items["A"], 16 ) - b = int( items["B"], 16 ) - c = int( items["C"], 16 ) - d = int( items["D"], 16 ) - pr = int( items["PR"], 16 ) - tr = int( items["TR"], 16 ) - - if tr >= c5: - dut = tr - c5 - (tr-c5)/128.0 * (tr-c5)/128.0 * a/2**c - else: - dut = tr - c5 - (tr-c5)/128.0 * (tr-c5)/128.0 * b/2**c - - off = (c2 + (c4 - 1024) * dut / 16384.0) * 4 - sens = c1 + c3 * dut / 1024.0 - x = sens * (pr - 7168) / 16384.0 - off - p = x * 10 / 32 + c7 + 760.0 - - data.id = items.get( "id", "Unknown" ) - data.pressure = round( p / 338.637526, 2 ) # Convert to HgIn - -#=========================================================================== -def _readSignal( data, items, key, value ): - data.signal = float( value ) / 4.0 - -#=========================================================================== -def _readBattery( data, items, key, value ): - data.battery = batteryMap.get( value, 0 ) - -#=========================================================================== -def _readWindDir( data, items, key, value ): - data.windDir = windMap.get( value, None ) - -#=========================================================================== -def _readWindSpeed( data, items, key, value ): - """ A0aaaabbbbb == aaaa.bbbbb cm/sec - """ - cmPerSec = float( value[2:6] ) + float( value[6:10] ) / 1e4 - data.windSpeed = round( cmPerSec / 44.704, 2 ) - -#=========================================================================== -def _readTemp( data, items, key, value ): - """ Aaaabbbbbb == aaa.bbbbbb deg C - """ - degC = float( value[1:4] ) + float( value[4:10] ) / 1e6 - data.temperature = round( degC * 1.8 + 32, 1 ) - -#=========================================================================== -def _readHumidity( data, items, key, value ): - """ Aaaabbbbbb == aaa.bbbbbb percentage - """ - data.humidity = float( value[1:4] ) + float( value[4:10] ) / 1e6 - -#=========================================================================== -def _readRainfall( data, items, key, value ): - """ A0aabbbb == aa.bbbb cm in the last 36 seconds - """ - cm = float( value[2:4] ) + float( value[4:8] ) / 1e4 - data.rainfall = round( cm / 25.4, 3 ) - -#=========================================================================== -handlers = { - "sensor" : _readSensor, - "mt" : _readPressure, - "windspeed" : _readWindSpeed, - "winddir" : _readWindDir, - "temperature" : _readTemp, - "humidity" : _readHumidity, - "rainfall" : _readRainfall, - "battery" : _readBattery, - "rssi" : _readSignal, - } - -#=========================================================================== diff --git a/Docker/src/python/tHome/acurite/mqtt.py b/Docker/src/python/tHome/acurite/mqtt.py deleted file mode 100644 index b0aacd7..0000000 --- a/Docker/src/python/tHome/acurite/mqtt.py +++ /dev/null @@ -1,79 +0,0 @@ -#=========================================================================== -# -# Convert decoded data to MQTT messages. -# -#=========================================================================== - -#=========================================================================== -def convert( config, data ): - # List of tuples of ( topic, payload ) where payload is a dictionary. - msgs = [] - - if hasattr( data, "battery" ): - topic = config.mqttBattery % data.location - payload = { - "time" : data.time, - "battery" : data.battery, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "signal" ): - topic = config.mqttRssi % data.location - payload = { - "time" : data.time, - # Input is 0->1, convert to 0->100 - "rssi" : data.signal * 100, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "humidity" ): - topic = config.mqttHumidity % data.location - payload = { - "time" : data.time, - "humidity" : data.humidity, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "temperature" ): - topic = config.mqttTemp % data.location - payload = { - "time" : data.time, - "temperature" : data.temperature, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "windSpeed" ): - topic = config.mqttWindSpeed % data.location - payload = { - "time" : data.time, - "speed" : data.windSpeed, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "windDir" ): - topic = config.mqttWindDir % data.location - payload = { - "time" : data.time, - "direction" : data.windDir, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "pressure" ): - topic = config.mqttBarometer % data.location - payload = { - "time" : data.time, - "pressure" : data.pressure, - } - msgs.append( ( topic, payload ) ) - - if hasattr( data, "rainfall" ): - topic = config.mqttRain % data.location - payload = { - "time" : data.time, - "rain" : data.rainfall, - } - msgs.append( ( topic, payload ) ) - - return msgs - -#=========================================================================== diff --git a/Docker/src/python/tHome/acurite/test/parse.py b/Docker/src/python/tHome/acurite/test/parse.py deleted file mode 100755 index a0009a9..0000000 --- a/Docker/src/python/tHome/acurite/test/parse.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python - -from tHome import acurite - -sensorMap = {} - -for l in open( "/home/ted/weather.log", "r" ): - p = acurite.decode( l, sensorMap ) - if p: - print p - diff --git a/Docker/src/python/tHome/acurite/test/process.py b/Docker/src/python/tHome/acurite/test/process.py deleted file mode 100755 index f88fd65..0000000 --- a/Docker/src/python/tHome/acurite/test/process.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python - -from tHome import acurite - -sensors = [ - acurite.Sensor( "08260", "Garage" ), - acurite.Sensor( "09096", "Kitchen" ), - acurite.Sensor( "00414", "Backyard" ), - acurite.Sensor( "24C86E0449A0", "Bridge" ), - acurite.Sensor( "05250", "Courtyard", humidity=False ), - acurite.Sensor( "16039", "Rec Room", humidity=False ), - acurite.Sensor( "02717", "Front Bedroom", humidity=False ), - acurite.Sensor( "05125", "Den", humidity=False ), - acurite.Sensor( "08628", "Garage 2", humidity=False ), - acurite.Sensor( "09338", "Side Bedroom", humidity=False ), - acurite.Sensor( "01948", "Master Closet", humidity=False ), - acurite.Sensor( "15116", "Attic", humidity=False ), - acurite.Sensor( "05450", "Master Bath", humidity=False ), - ] - -sensorMap = {} -for s in sensors: - sensorMap[s.id] = s - -for l in open( "/home/ted/weather.log", "r" ): - r = acurite.cmdLine.process( l, sensorMap ) - if r: - print r - diff --git a/Docker/src/python/tHome/acurite/test/run.py b/Docker/src/python/tHome/acurite/test/run.py deleted file mode 100755 index cdb111d..0000000 --- a/Docker/src/python/tHome/acurite/test/run.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -from tHome import acurite - -acurite.run() - diff --git a/Docker/src/python/tHome/sma/Auth.py b/Docker/src/python/tHome/sma/Auth.py deleted file mode 100644 index d23bdd3..0000000 --- a/Docker/src/python/tHome/sma/Auth.py +++ /dev/null @@ -1,127 +0,0 @@ -#=========================================================================== -# -# Log on/off packets -# -#=========================================================================== - -import logging -import socket -import time -# Import the base header and the struct type codes we're using. -from .Header import * -from .. import util - -#=========================================================================== -class LogOn ( Header ): - _fields = Header._fields + [ - ( uint4, 'command' ), - ( uint4, 'group' ), - ( uint4, 'timeout' ), - ( uint4, 'time' ), - ( uint4, 'unknown1' ), - ( '12s', "password" ), - ( uint4, 'trailer' ), - ] - - struct = util.NamedStruct( 'LITTLE_ENDIAN', _fields ) - - #------------------------------------------------------------------------ - def __init__( self, group, password ): - assert( len( password ) <= 12 ) - assert( group == "USER" or group == "INSTALLER" ) - - Header.__init__( self ) - - if group == "USER": - self.group = 0x00000007 - passOffset = 0x88 - else: # installer - self.group = 0x0000000A - passOffset = 0xBB - - self.password = "" - - # Loop over each character and encode it as hex and offset by - # the group code offset. - for i in range( 12 ): - if i < len( password ): - c = int( password[i].encode( 'hex' ), 16 ) + passOffset - - # Pad out to 12 bytes w/ the group code offset. - else: - c = passOffset - - # Turn the hex code back to a character. - self.password += chr( c ) - - self.destCtrl = 0x0100 - self.srcCtrl = 0x0100 - - self.command = 0xFFFD040C - self.timeout = 0x00000384 # 900 sec - self.time = int( time.time() ) - self.unknown1 = 0x00 - self.trailer = 0x00 - - #------------------------------------------------------------------------ - def send( self, sock ): - # Pack ourselves into the message structure. - bytes = self.struct.pack( self ) - - if self._log.isEnabledFor( logging.DEBUG ): - self._log.debug( "Send: LogOn packet\n" + util.hex.dump( bytes ) ) - - try: - # Send the message and receive the response back. - sock.send( bytes ) - bytes = sock.recv( 4096 ) - - except socket.timeout as e: - msg = "Can't log on - time out error" - self._log.error( msg ) - util.Error.raiseException( e, msg ) - - if self._log.isEnabledFor( logging.DEBUG ): - self._log.debug( "Recv: LogOn reply\n" + util.hex.dump( bytes ) ) - - # Overwrite our fields w/ the reply data. - self.struct.unpack( self, bytes ) - if self.error: - raise util.Error( "Error trying to log on to the SMA inverter. " - "Group/password failed." ) - - #------------------------------------------------------------------------ - -#=========================================================================== -class LogOff ( Header ): - _fields = Header._fields + [ - ( uint4, 'command' ), - ( uint4, 'unknown1' ), - ( uint4, 'trailer' ), - ] - - struct = util.NamedStruct( 'LITTLE_ENDIAN', _fields ) - - #------------------------------------------------------------------------ - def __init__( self ): - Header.__init__( self ) - - self.destCtrl = 0x0300 - self.srcCtrl = 0x0300 - - self.command = 0xFFFD010E - self.unknown1 = 0xFFFFFFFF - self.trailer = 0x00 - - #------------------------------------------------------------------------ - def send( self, sock ): - bytes = self.struct.pack( self ) - - if self._log.isEnabledFor( logging.DEBUG ): - self._log.debug( "Send: LogOff packet\n" + util.hex.dump( bytes ) ) - - sock.send( bytes ) - - #------------------------------------------------------------------------ - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/Header.py b/Docker/src/python/tHome/sma/Header.py deleted file mode 100644 index 02890db..0000000 --- a/Docker/src/python/tHome/sma/Header.py +++ /dev/null @@ -1,92 +0,0 @@ -#=========================================================================== -# -# Common data packet structures. Used for requests and replies. -# -#=========================================================================== -from .. import util - -#=========================================================================== - -# Struct type codes -uint1 = "B" -uint2 = "H" -uint4 = "I" -uint8 = "Q" -int1 = "b" -int2 = "h" -int4 = "i" -int8 = "q" - -#============================================================================== -class Header: - _fields = [ - # Header fields - ( uint4, 'hdrMagic' ), - ( uint4, 'hdrUnknown1' ), - ( uint4, 'hdrUnknown2' ), - ( uint1, 'packetHi' ), # packet length in little endian hi word - ( uint1, 'packetLo' ), # packet length in little endian low word - ( uint4, 'signature' ), - ( uint1, 'wordLen' ), # int( packetLen / 4 ) - ( uint1, 'hdrUnknown3' ), - # Common packet fields - ( uint2, 'destId', ), - ( uint4, 'destSerial', ), - ( uint2, 'destCtrl', ), - ( uint2, 'srcId', ), - ( uint4, 'srcSerial', ), - ( uint2, 'srcCtrl', ), - ( uint2, 'error', ), - ( uint2, 'fragmentId', ), - ( uint1, 'packetId', ), - ( uint1, 'baseUnknown', ), - ] - - _hdrSize = 20 # bytes for the header fields. - _nextPacketId = 0 - - #------------------------------------------------------------------------ - def __init__( self ): - assert( self.struct ) - - self.hdrMagic = 0x00414D53 - self.hdrUnknown1 = 0xA0020400 - self.hdrUnknown2 = 0x01000000 - self.signature = 0x65601000 - self.hdrUnknown3 = 0xA0 - - # NOTE: self.struct must be created by the derived class. That - # allows this to compute the correct packet length and encode it. - packetLen = len( self.struct ) - self._hdrSize - self.packetHi = ( packetLen >> 8 ) & 0xFF - self.packetLo = packetLen & 0xFF - self.wordLen = int( packetLen / 4 ) - - # Any destination - we send to a specific IP address so this - # isn't important. - self.destId = 0xFFFF - self.destSerial = 0xFFFFFFFF - self.destCtrl = 0x00 - self.srcId = 0x7d # TODO change this? - self.srcSerial = 0x334657B0 # TODO change this? - self.srcCtrl = 0x00 - self.error = 0 - self.fragmentId = 0 - self.baseUnknown = 0x80 - - # Packet id is 1 byte so roll over at 256. - self._nextPacketId += 1 - if self._nextPacketId == 256: - self._nextPacketId = 1 - - self.packetId = self._nextPacketId - - self._log = util.log.get( "sma" ) - - #------------------------------------------------------------------------ - def bytes( self ): - return self.struct.pack( self ) - - #------------------------------------------------------------------------ - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/Link.py b/Docker/src/python/tHome/sma/Link.py deleted file mode 100644 index 5a44f54..0000000 --- a/Docker/src/python/tHome/sma/Link.py +++ /dev/null @@ -1,240 +0,0 @@ -#=========================================================================== -# -# Primary SMA API. -# -#=========================================================================== - -import socket -from .. import util -from . import Auth -from . import Reply -from . import Request - -#============================================================================== -class Link: - """SMA WebConnection link - - Units: Watt, Watt-hours, C, seconds - - l = Link( '192.168.1.14' ) - print l.acTotalEnergy() - - See also: report for common requests. - """ - def __init__( self, ip, port=9522, group="USER", password="0000", - connect=True, timeout=120, decode=True, raw=False ): - if group != "USER" and group != "INSTALLER": - raise util.Error( "Invalid group '%s'. Valid groups are 'USER' " - "'INSTALLER'." % group ) - - self.ip = ip - self.port = port - self.group = group - self.password = password - self.timeout = timeout - self.decode = decode - self.raw = raw - - self.socket = None - if connect: - self.open() - - #--------------------------------------------------------------------------- - def info( self ): - p = Request.Data( command=0x58000200, first=0x00821E00, last=0x008220FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.StringItem( "name", 40, timeVar="timeWake" ), - Reply.AttrItem( "type", 40 ), - Reply.AttrItem( "model", 40 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def status( self ): - p = Request.Data( command=0x51800200, first=0x00214800, last=0x002148FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.AttrItem( "status", 32, timeVar="time" ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def gridRelayStatus( self ): - p = Request.Data( command=0x51800200, first=0x00416400, last=0x004164FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.AttrItem( "gridStatus", 32, timeVar="timeOff" ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def temperature( self ): - """Return the inverter temp in deg C (or 0 if unavailable).""" - p = Request.Data( command=0x52000200, first=0x00237700, last=0x002377FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I32Item( "temperature", 16, mult=0.01 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def version( self ): - """Return the inverter software version string.""" - p = Request.Data( command=0x58000200, first=0x00823400, last=0x008234FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.VersionItem( "version" ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def acTotalEnergy( self ): - p = Request.Data( command=0x54000200, first=0x00260100, last=0x002622FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I64Item( "totalEnergy", 16, mult=1.0, timeVar="timeLast" ), - Reply.I64Item( "dailyEnergy", 16, mult=1.0 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def acTotalPower( self ): - p = Request.Data( command=0x51000200, first=0x00263F00, last=0x00263FFF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I32Item( "acPower", 28, mult=1.0, timeVar="timeOff" ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def acPower( self ): - p = Request.Data( command=0x51000200, first=0x00464000, last=0x004642FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I32Item( "acPower1", 28, mult=1.0, timeVar="timeOff" ), - Reply.I32Item( "acPower2", 28, mult=1.0 ), - Reply.I32Item( "acPower3", 28, mult=1.0 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def acMaxPower( self ): - p = Request.Data( command=0x51000200, first=0x00411E00, last=0x004120FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.U32Item( "acMaxPower1", 28, mult=1.0, timeVar="time" ), - Reply.U32Item( "acMaxPower2", 28, mult=1.0 ), - Reply.U32Item( "acMaxPower3", 28, mult=1.0 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def operationTime( self ): - p = Request.Data( command=0x54000200, first=0x00462E00, last=0x00462FFF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I64Item( "operationTime", 16, mult=1.0, timeVar="timeLast" ), - Reply.I64Item( "feedTime", 16, mult=1.0 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def dcPower( self ): - p = Request.Data( command=0x53800200, first=0x00251E00, last=0x00251EFF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I32Item( "dcPower1", 28, mult=1.0, timeVar="timeOff" ), - Reply.I32Item( "dcPower2", 28, mult=1.0 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def dcVoltage( self ): - p = Request.Data( command=0x53800200, first=0x00451F00, last=0x004521FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.I32Item( "dcVoltage1", 28, mult=0.01, timeVar="timeOff" ), - Reply.I32Item( "dcVoltage2", 28, mult=0.01 ), - Reply.I32Item( "dcCurrent1", 28, mult=0.001 ), - Reply.I32Item( "dcCurrent2", 28, mult=0.001 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def acVoltage( self ): - p = Request.Data( command=0x51000200, first=0x00464800, last=0x004652FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.U32Item( "acVoltage1", 28, mult=0.01, timeVar="timeOff" ), - Reply.U32Item( "acVoltage2", 28, mult=0.01 ), - Reply.U32Item( "acVoltage3", 28, mult=0.01 ), - Reply.U32Item( "acGridVoltage", 28, mult=0.01 ), - Reply.U32Item( "unknown1", 28, mult=0.01 ), - Reply.U32Item( "unknown2", 28, mult=0.01 ), - Reply.U32Item( "acCurrent1", 28, mult=0.001 ), - Reply.U32Item( "acCurrent2", 28, mult=0.001 ), - Reply.U32Item( "acCurrent3", 28, mult=0.001 ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def gridFrequency( self ): - p = Request.Data( command=0x51000200, first=0x00465700, last=0x004657FF ) - bytes = p.send( self.socket ) - decoder = Reply.Value( [ - Reply.U32Item( "frequency", 28, mult=0.01, timeVar="timeOff" ), - ] ) - return self._return( bytes, decoder ) - - #--------------------------------------------------------------------------- - def __del__( self ): - self.close() - - #--------------------------------------------------------------------------- - def open( self ): - if self.socket: - return - - self.socket = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) - self.socket.settimeout( self.timeout ) - try: - self.socket.connect( ( self.ip, self.port ) ) - - p = Auth.LogOn( self.group, self.password ) - p.send( self.socket ) - except: - if self.socket: - self.socket.close() - - self.socket = None - raise - - #--------------------------------------------------------------------------- - def close( self ): - if not self.socket: - return - - p = Auth.LogOff() - try: - p.send( self.socket ) - finally: - self.socket.close() - self.socket = None - - #--------------------------------------------------------------------------- - def __enter__( self ): - return self - - #--------------------------------------------------------------------------- - def __exit__( self, type, value, traceback ): - self.close() - - #--------------------------------------------------------------------------- - def _return( self, bytes, decoder ): - if self.decode: - return decoder.decode( bytes, self.raw ) - else: - return ( bytes, decoder ) - -#============================================================================== diff --git a/Docker/src/python/tHome/sma/Reply.py b/Docker/src/python/tHome/sma/Reply.py deleted file mode 100644 index 3ca3ed8..0000000 --- a/Docker/src/python/tHome/sma/Reply.py +++ /dev/null @@ -1,225 +0,0 @@ -#=========================================================================== -# -# Data reply packets -# -#=========================================================================== - -import struct -from .. import util -# Import the base header and the struct type codes we're using. -from .Header import * -from . import tags - -#=========================================================================== - -class Value ( Header, util.Data ): - _fields = Header._fields + [ - ( uint4, 'command' ), - ( uint4, 'first' ), - ( uint4, 'last' ), - ] - - struct = util.NamedStruct( 'LITTLE_ENDIAN', _fields ) - - def __init__( self, decoders ): - self.values = [] - self._decoders = decoders - Header.__init__( self ) - util.Data.__init__( self ) - - def __call__( self, bytes, raw=False, obj=None ): - return self.decode( bytes, raw, obj ) - - def decode( self, bytes, raw=False, obj=None ): - # Unpack the base data. - self.struct.unpack( self, bytes ) - - offset = len( self.struct ) - for d in self._decoders: - offset += d.decodeItem( self, bytes, offset ) - - if raw: - return self - - r = obj if obj is not None else util.Data() - for item in self.values: - for varFrom, varTo in item._variables: - value = getattr( item, varFrom ) - setattr( r, varTo, value ) - - return r - -#============================================================================== -class BaseItem ( util.Data ): - _fields = [ - ( uint1, 'mppNum' ), - ( uint2, 'msgType' ), - ( uint1, 'dataType' ), - ( uint4, 'time' ), - ] - - _baseSize = 8 # bytes - - def __init__( self, var, size, timeVar=None ): - self.variable = var - self._size = size - - self._variables = [] - if timeVar: - self._variables.append( ( 'time', timeVar ) ) - - util.Data.__init__( self ) - - def decodeBase( self, obj, attrVal ): - setattr( obj, self.variable, attrVal ) - obj.values.append( self ) - - return self._size - -#============================================================================== -class StringItem ( BaseItem ): - def __init__( self, var, size, timeVar=None ): - BaseItem.__init__( self, var, size, timeVar ) - - self._fields = BaseItem._fields + [ - ( '%ds' % ( size - BaseItem._baseSize ), "bytes" ), - ] - self._struct = util.NamedStruct( 'LITTLE_ENDIAN', self._fields ) - - self._variables.append( ( 'value', var ) ) - - def decodeItem( self, obj, bytes, offset ): - self._struct.unpack( self, bytes, offset ) - - s = self.bytes - idx = s.find( "\0" ) - if idx != -1: - s = s[:idx] - - self.value = s - - return BaseItem.decodeBase( self, obj, self.value ) - - -#============================================================================== -class AttrItem ( BaseItem ): - struct = util.NamedStruct( 'LITTLE_ENDIAN', BaseItem._fields ) - - def __init__( self, var, size, timeVar=None ): - BaseItem.__init__( self, var, size, timeVar ) - - self._numAttr = ( size - BaseItem._baseSize ) / 4 - self._variables.append( ( 'value', var ) ) - - def decodeItem( self, obj, bytes, offset ): - self.struct.unpack( self, bytes, offset ) - offset += len( self.struct ) - - # Little endian, 4 individual unsigned bytes - s = struct.Struct( ' 5: - relType = str( self.verType ) - else: - relType = "NEABRS"[self.verType] - - self.version = '%02x.%02x.%02x.%s' % ( self.verMajor, self.verMinor, - self.verBuild, relType ) - - return BaseItem.decodeBase( self, obj, self.version ) - - -#============================================================================== - diff --git a/Docker/src/python/tHome/sma/Request.py b/Docker/src/python/tHome/sma/Request.py deleted file mode 100644 index 0117400..0000000 --- a/Docker/src/python/tHome/sma/Request.py +++ /dev/null @@ -1,58 +0,0 @@ -#=========================================================================== -# -# Data request packet -# -#=========================================================================== - -import logging -import socket -# Import the base header and the struct type codes we're using. -from .Header import * -from .. import util - -#=========================================================================== -class Data ( Header ): - _fields = Header._fields + [ - ( uint4, 'command' ), - ( uint4, 'first' ), - ( uint4, 'last' ), - ( uint4, 'trailer' ), - ] - - struct = util.NamedStruct( 'LITTLE_ENDIAN', _fields ) - - #------------------------------------------------------------------------ - def __init__( self, command, first, last ): - Header.__init__( self ) - - self.command = command - self.first = first - self.last = last - self.trailer = 0x00 - - #------------------------------------------------------------------------ - def send( self, sock ): - bytes = self.struct.pack( self ) - - if self._log.isEnabledFor( logging.DEBUG ): - self._log.debug( "Send: Request.Data packet\n" + - util.hex.dump( bytes ) ) - - # Send the request and read the reply back in. - try: - sock.send( bytes ) - reply = sock.recv( 4096 ) - - except socket.timeout as e: - msg = "Data request failed - time out error" - self._log.error( msg ) - util.Error.raiseException( e, msg ) - - if self._log.isEnabledFor( logging.DEBUG ): - self._log.debug( "Recv: Reply packet\n" + util.hex.dump( reply ) ) - - return reply - - #------------------------------------------------------------------------ - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/__init__.py b/Docker/src/python/tHome/sma/__init__.py deleted file mode 100644 index d887b27..0000000 --- a/Docker/src/python/tHome/sma/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -#=========================================================================== -# -# SMA inverter module -# -#=========================================================================== - -__doc__ = """Read SMA Solar inverter data. - -See Link and report for the main programming interfaces. - -See cmdLine for a main program to poll the inverter and send out MQTT -messges. -""" - -#=========================================================================== - -from . import Auth -from . import cmdLine -from . import config -from .Header import Header -from .Link import Link -from . import Reply -from . import report -from . import Request -from . import start -from . import tags - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/cmdLine.py b/Docker/src/python/tHome/sma/cmdLine.py deleted file mode 100644 index aba5355..0000000 --- a/Docker/src/python/tHome/sma/cmdLine.py +++ /dev/null @@ -1,49 +0,0 @@ -#=========================================================================== -# -# Command line processing -# -#=========================================================================== - -import argparse -from .. import broker -from . import config -from . import start - -#=========================================================================== - -def run( args ): - """Parse command line arguments to poll the inverter. - - = INPUTS - - args [str]: List of command line arguments. [0] should be the - program name. - """ - p = argparse.ArgumentParser( prog=args[0], - description="SMA inverter reader" ) - p.add_argument( "-c", "--configDir", metavar="configDir", - default="/var/config/tHome", - help="T-Home configuration directory." ) - p.add_argument( "-l", "--log", metavar="logFile", - default=None, help="Logging file to use. Input 'stdout' " - "to log to the screen." ) - p.add_argument( "--debug", default=False, action="store_true", - help="Debugging - no sending, just print" ) - c = p.parse_args( args[1:] ) - - if c.debug: - c.log = "stdout" - - # Parse the sma and broker config files. - cfg = config.parse( c.configDir ) - log = config.log( cfg, c.log ) - - if c.debug: - log.setLevel( 10 ) - - # Create the MQTT client and connect it to the broker. - client = broker.connect( c.configDir, log ) - - start.start( cfg, client, debug=c.debug ) - - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/config.py b/Docker/src/python/tHome/sma/config.py deleted file mode 100644 index 051d5ed..0000000 --- a/Docker/src/python/tHome/sma/config.py +++ /dev/null @@ -1,49 +0,0 @@ -#=========================================================================== -# -# Config file -# -#=========================================================================== - -__doc__ = """Config file parsing. -""" - -from .. import util -from ..util import config as C - -#=========================================================================== - -# Config file section name and defaults. -configEntries = [ - # ( name, converter function, default value ) - C.Entry( "host", str ), - C.Entry( "port", int, 9522 ), - C.Entry( "group", str, "USER" ), - C.Entry( "password", str, "0000" ), - C.Entry( "logFile", util.path.expand ), - C.Entry( "logLevel", int, 20 ), # INFO - C.Entry( "pollPower", int, 10 ), - C.Entry( "pollEnergy", int, 600 ), # 10 minutes - C.Entry( "pollFull", int, 0 ), # disabled - C.Entry( "mqttEnergy", str, "elec/solar/meter" ), - C.Entry( "mqttPower", str, "elec/solar/instant" ), - C.Entry( "mqttFull", str, "elec/solar/detail" ), - C.Entry( "lat", float ), - C.Entry( "lon", float ), - C.Entry( "timePad", float, 600 ), # 10 minutes - ] - -#=========================================================================== -def parse( configDir, configFile='sma.py' ): - return C.readAndCheck( configDir, configFile, configEntries ) - -#=========================================================================== -def log( config, logFile=None ): - if not logFile: - logFile = config.logFile - - return util.log.get( "sma", config.logLevel, logFile ) - -#=========================================================================== - - - diff --git a/Docker/src/python/tHome/sma/report.py b/Docker/src/python/tHome/sma/report.py deleted file mode 100644 index 0678623..0000000 --- a/Docker/src/python/tHome/sma/report.py +++ /dev/null @@ -1,99 +0,0 @@ -#=========================================================================== -# -# Report functions -# -#=========================================================================== -import time -from ..util import Data -from .Link import Link - -#=========================================================================== -def power( *args, **kwargs ): - """Return instantaneous AC and DC power generation. - - Inputs are the same as Link() constructor: - - obj = report.instant( '192.168.1.15' ) - print obj - """ - with Link( *args, **kwargs ) as link: - link.decode = False - link.raw = False - dcBytes, dc = link.dcPower() - acBytes, ac = link.acTotalPower() - - now = time.time() - obj = dc.decode( dcBytes ) - obj.update( ac.decode( acBytes ) ) - - obj.time = now - obj.dcPower = obj.dcPower1 + obj.dcPower2 - return obj - -#=========================================================================== -def energy( *args, **kwargs ): - """Return instantaneous power and total energy status. - - Get instantaneous AC and DC power generation and energy created for - the day. - - Inputs are the same as Link() constructor: - - obj = report.energy( '192.168.1.15' ) - print obj - """ - with Link( *args, **kwargs ) as link: - link.decode = False - dcBytes, dc = link.dcPower() - acBytes, ac = link.acTotalPower() - totBytes, total = link.acTotalEnergy() - - now = time.time() - obj = dc.decode( dcBytes ) - obj.update( ac.decode( acBytes ) ) - obj.update( total.decode( totBytes ) ) - - obj.time = now - obj.dcPower = obj.dcPower1 + obj.dcPower2 - return obj - -#=========================================================================== -def full( *args, **kwargs ): - """Return all possible fields. - - Inputs are the same as Link() constructor: - - obj = report.full( '192.168.1.15' ) - print obj - """ - funcs = [ - Link.info, - Link.status, - Link.gridRelayStatus, - Link.temperature, - Link.version, - Link.acTotalEnergy, - Link.acTotalPower, - Link.acPower, - Link.acMaxPower, - Link.operationTime, - Link.dcPower, - Link.dcVoltage, - Link.acVoltage, - Link.gridFrequency, - ] - - with Link( *args, **kwargs ) as link: - link.decode = False - results = [ f( link ) for f in funcs ] - - now = time.time() - obj = Data() - for bytes, decoder in results: - obj.update( decoder.decode( bytes ) ) - - obj.time = now - obj.dcPower = obj.dcPower1 + obj.dcPower2 - return obj - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/start.py b/Docker/src/python/tHome/sma/start.py deleted file mode 100644 index 0778567..0000000 --- a/Docker/src/python/tHome/sma/start.py +++ /dev/null @@ -1,207 +0,0 @@ -#=========================================================================== -# -# Main report processing -# -#=========================================================================== - -import astral -import calendar -import datetime -import json -import time -from .. import util -from . import report - -#=========================================================================== -def start( config, client, debug=False ): - fromts = datetime.datetime.fromtimestamp - - log = util.log.get( "sma" ) - - linkArgs = { "ip" : config.host, "port" : config.port, - "group" : config.group, "password" : config.password, } - - reports = [] - if config.pollFull > 0: - reports.append( util.Data( lbl="full", func=msgFull, - poll=config.pollFull, nextT=0 ) ) - - if config.pollEnergy > 0: - reports.append( util.Data( lbl="energy", func=msgEnergy, - poll=config.pollEnergy, nextT=0 ) ) - - if config.pollPower > 0: - reports.append( util.Data( lbl="power", func=msgPower, - poll=config.pollPower, nextT=0 ) ) - - if not reports: - log.error( "No reports specified, all poll times <= 0" ) - return - - t0 = time.time() - - useRiseSet = ( config.lat is not None and config.lon is not None ) - - log.info( "Startup time : %s" % fromts( t0 ) ) - if useRiseSet: - timeRise = sunRise( config.lat, config.lon ) - timeSet = sunSet( config.lat, config.lon ) - log.info( "Today's sun rise: %s" % fromts( timeRise ) ) - log.info( "Today's sun set : %s" % fromts( timeSet ) ) - else: - timeRise = 0 - timeSet = 3e9 # jan, 2065 - - # Current time is before todays sun rise. Start reporting at the - # rise time and stop reporting at the set time. - if t0 < timeRise: - timeBeg = timeRise - config.timePad - timeEnd = timeSet + config.timePad - log.info( "Before sun rise, sleeping until %s" % fromts( timeBeg ) ) - - # Current time is after todays sun set. Start reporting at - # tomorrows rise time and stop reporting at tomorrows set time. - elif t0 > timeSet: - timeBeg = sunRise( config.lat, config.lon, +1 ) - config.timePad - timeEnd = sunSet( config.lat, config.lon, +1 ) + config.timePad - log.info( "After sun set, sleeping until %s" % fromts( timeBeg ) ) - - # Current time is between todays rise and set. Start reporting - # immediately and stop reporting at the set time. - else: - timeBeg = t0 - timeEnd = timeSet + config.timePad - log.info( "Sun up, run until sunset %s" % fromts( timeEnd ) ) - - _initTimes( reports, timeBeg ) - - while True: - nextReport = min( reports, key=lambda x: x.nextT ) - - dt = nextReport.nextT - t0 - if dt > 0: - log.info( "Sleeping %s sec for report %s" % ( dt, nextReport.lbl ) ) - time.sleep( dt ) - - log.info( "Running report : %s" % nextReport.lbl ) - try: - nextReport.func( client, linkArgs, config, log ) - except: - log.exception( "Report failed to run" ) - - nextReport.nextT += nextReport.poll - - t0 = time.time() - - # Time is now after the end time for today. - if t0 > timeEnd: - # If the last report wasn't the largest one, run the largest - # report one last time. This gives us a final tally of - # energy production for example. - if nextReport != reports[0]: - reports[0].func( client, linkArgs, config, log ) - - timeBeg = sunRise( config.lat, config.lon, +1 ) - config.timePad - timeEnd = sunSet( config.lat, config.lon, +1 ) + config.timePad - _initTimes( reports, timeBeg ) - - log.info( "After sun set, sleeping until %s" % fromts( timeBeg ) ) - - -#=========================================================================== -def sunRise( lat, lon, dayOffset=0 ): - t = datetime.date.today() + datetime.timedelta( days=dayOffset ) - - a = astral.Astral() - utc = a.sunrise_utc( t, lat, lon ) - - # Convert the UTC datetime to a UNIX time stamp. - return calendar.timegm( utc.timetuple() ) - -#=========================================================================== -def sunSet( lat, lon, dayOffset=0 ): - t = datetime.date.today() + datetime.timedelta( days=dayOffset ) - - a = astral.Astral() - utc = a.sunset_utc( t, lat, lon ) - - # Convert the UTC datetime to a UNIX time stamp. - return calendar.timegm( utc.timetuple() ) - -#=========================================================================== -def msgPower( client, linkArgs, config, log ): - data = report.power( **linkArgs ) - msg = _buildPowerMsg( data, log ) - - payload = json.dumps( msg ) - - log.info( "Publish: %s: %s" % ( config.mqttPower, payload ) ) - client.publish( config.mqttPower, payload ) - -#=========================================================================== -def msgEnergy( client, linkArgs, config, log ): - data = report.energy( **linkArgs ) - - msgs = [ - # ( topic name, msg dict ) - ( config.mqttPower, _buildPowerMsg( data, log ) ), - ( config.mqttEnergy, _buildEnergyMsg( data, log ) ), - ] - - for topic, data in msgs: - payload = json.dumps( data ) - - log.info( "Publish: %s: %s" % ( topic, payload ) ) - client.publish( topic, payload ) - -#=========================================================================== -def msgFull( client, linkArgs, config, log ): - data = report.full( **linkArgs ) - - msgs = [ - # ( topic name, msg dict ) - ( config.mqttPower, _buildPowerMsg( data, log ) ), - ( config.mqttEnergy, _buildEnergyMsg( data, log ) ), - ( config.mqttFull, _buildFullMsg( data, log ) ), - ] - - for topic, data in msgs: - payload = json.dumps( data ) - client.publish( topic, payload ) - -#=========================================================================== -def _buildPowerMsg( data, log ): - msg = { - "time" : data["time"], - "acPower" : data["acPower"], # in W - "dcPower" : data["dcPower"], # in W - } - - log.info( "AC power: %(acPower)s W", msg ) - return msg - -#=========================================================================== -def _buildEnergyMsg( data, log ): - msg = { - "time" : data["time"], - "dailyEnergy" : data["dailyEnergy"] / 1000.0, # Wh -> kWh - "totalEnergy" : data["totalEnergy"] / 1000.0, # Wh -> kWh - } - - log.info( "Daily energy: %(dailyEnergy)s kWh", msg ) - return msg - -#=========================================================================== -def _buildFullMsg( data, log ): - return data.__dict__ - -#=========================================================================== -def _initTimes( reports, timeBeg ): - # Set the first time to be the begin time + the polling interval. - for r in reports: - r.nextT = timeBeg + r.poll - - # Run the biggest priority report once right at startup. - reports[0].nextT = timeBeg - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/tags.py b/Docker/src/python/tHome/sma/tags.py deleted file mode 100644 index ff873f9..0000000 --- a/Docker/src/python/tHome/sma/tags.py +++ /dev/null @@ -1,3431 +0,0 @@ -#=========================================================================== -# -# SMA attribute tags -> string values. -# -# Values take from SMASpot software TagListEN-US.txt file. -# https://sbfspot.codeplex.com/ -# -#=========================================================================== - -values = { - 1 : "%", - 2 : "C", - 3 : "A", - 4 : "dBm", - 5 : "deg", - 6 : "h", - 7 : "Hz", - 8 : "kWh", - 9 : "m/s", - 10 : "ms", - 11 : "Ohm", - 12 : "Pa", - 13 : "s", - 14 : "V", - 15 : "VA", - 16 : "var", - 17 : "W/m2", - 18 : "W", - 19 : "Wh", - 20 : "Phase currents", - 21 : "Number grid connections device", - 22 : "Total operating time of device", - 23 : "Total feed-in time of device", - 24 : "Total energy absorbed from the grid by the device", - 25 : "Total energy fed by device", - 26 : "Acknowledge fault", - 27 : "Special setting", - 28 : "Islanding detection", - 29 : "Number of detections", - 30 : "Time of the last detection", - 31 : "K", - 32 : "F", - 33 : "W/s", - 34 : "min", - 35 : "Fault", - 36 : "Tripping threshold DC current monitoring", - 37 : "Tripping time DC current monitoring", - 38 : "Current", - 39 : "Operating condition current", - 40 : "Escalation factor", - 41 : "Operating condition current", - 42 : "AS4777.3", - 44 : "External", - 45 : "External 2", - 46 : "Battery", - 47 : "Maximum Bluetooth transmission power", - 48 : "Interior", - 49 : "Function", - 50 : "Status", - 51 : "Closed", - 52 : "Reset operating data", - 53 : "Country standard", - 54 : "Set country standard", - 55 : "Communication disturbed", - 56 : "Country settings", - 57 : "Constant voltage control", - 58 : "Cooling system", - 59 : "Data logging", - 60 : "Number of Flash write cycles", - 61 : "DC overcurrent", - 62 : "DC settings", - 63 : "Load parameter", - 64 : "DHCP", - 65 : "Intermediate circuit voltage", - 66 : "Start conditions not met", - 67 : "DC measurements", - 68 : "DC control", - 69 : "DC overvoltage", - 70 : "KiB", - 71 : "Interference of device", - 72 : "Load preset", - 73 : "Diffuse insolation", - 74 : "Direct insolation", - 75 : "DK5940E2.2", - 76 : "Fault correction measure", - 77 : "Check AC circuit breaker", - 78 : "Check generator", - 79 : "Disconnect generator", - 80 : "Check parameter", - 81 : "Check connection", - 82 : "Environment", - 83 : "UCE monitoring", - 84 : "Overcurrent grid (HW)", - 85 : "Overcurrent grid (SW)", - 86 : "Offset grid current sensor", - 87 : "Grid frequency disturbance", - 88 : "Grid frequency not permitted", - 89 : "Grid disconnection point", - 90 : "Deviation grid voltage measurement", - 91 : "Overvoltage grid (HW)", - 92 : "Grid overvoltage fast", - 93 : "Grid overvoltage slow", - 94 : "Grid overvoltage (spot value)", - 95 : "Grid undervoltage fast", - 96 : "Grid undervoltage slow", - 97 : "Grid voltage measurement Offset", - 98 : "Voltage increase protection", - 99 : "High discharge current", - 100 : "On-board supply system disturbance", - 101 : "General BSP fault", - 102 : "Events for developer", - 103 : "Events for installer", - 104 : "Events for service", - 105 : "Events for user", - 106 : "Execution (Reboot)", - 107 : "CPLD (HW)", - 108 : "CPLD version check", - 109 : "CPU self-test HP", - 110 : "DI converter fault", - 111 : "DI converter communication", - 112 : "Residual current", - 113 : "DI converter test current", - 114 : "Data storage blocked", - 115 : "Overcurrent input A (SW)", - 116 : "Overcurrent input B (SW)", - 117 : "Offset DC current sensor A", - 118 : "Offset DC current sensor B", - 119 : "DC grid feed-in", - 120 : "Overcurrent input A (HW)", - 121 : "Overcurrent input B (HW)", - 122 : "Overvoltage intermediate circuit (HW)", - 123 : "Overvoltage intermediate circuit (SW)", - 124 : "DC voltage measurement deviation", - 125 : "Overvoltage input A (SW)", - 126 : "Overvoltage input B (SW)", - 127 : "Generator voltage too low", - 128 : "DC power too low", - 129 : "DC converter string A defective", - 130 : "DC converter string B defective", - 131 : "Generator output too low", - 132 : "System data defective", - 133 : "System data access not possible", - 134 : "System data restored", - 135 : "External watchdog (enable)", - 136 : "Grid parameter unchanged", - 137 : "Waiting for main CPU", - 138 : "Grid parameter locked", - 139 : "Execution (Test HW)", - 140 : "Restart diagnosis system", - 141 : "Derating occurred", - 142 : "Execution (Taskinit)", - 143 : "Installer code invalid", - 144 : "Installer code valid", - 145 : "Relay defect", - 146 : "24 hour relay test", - 147 : "Execution (Mail)", - 148 : "Internal communication", - 149 : "Insulation failure", - 150 : "Sensor system insulation resistance", - 151 : "Relay insulation resistance", - 152 : "Current event number", - 153 : "Event number manufacturer", - 154 : "Grid failure", - 155 : "Island grid", - 156 : "Execution (Operation)", - 157 : "Execution", - 158 : "General OSL fault", - 159 : "Overtemperature interior", - 160 : "Overtemperature power unit", - 161 : "Varistor defective", - 162 : "PE not connected", - 163 : "L / N swapped", - 164 : "2nd phase connected to N", - 165 : "PLL outside limits", - 166 : "Memory defective", - 167 : "Reference voltage test", - 168 : "Code memory defective", - 169 : "SD card defective", - 170 : "SD card is read", - 171 : "Parameter file not found or defective", - 172 : "Set parameter", - 173 : "Parameter setting failed", - 174 : "Parameters set successfully", - 175 : "No new update on the SD card", - 176 : "Update file defective", - 177 : "Update file OK", - 178 : "No update file found", - 179 : "Execution (SharedMemory)", - 180 : "Self-test", - 181 : "Abort self-test", - 182 : "Abort self-test", - 183 : "Self-test current disconnection limit", - 184 : "Self-test standard value for display", - 185 : "Self-test disconnection time for display", - 186 : "Self-test disconnection limit for display", - 187 : "Long term data defective", - 188 : "Data storage defective", - 189 : "Execution (State machine)", - 190 : "Execution (Startup)", - 191 : "No system data", - 192 : "Fault sensor interior temperature", - 193 : "Fault sensor power unit temperature", - 194 : "Update Bluetooth", - 195 : "Update Bluetooth failed", - 196 : "Update completed", - 197 : "Update main CPU", - 198 : "Update main CPU failed", - 199 : "Update RS485I module", - 200 : "Update RS485I module failed", - 201 : "Update communication", - 202 : "Update language table", - 203 : "Update language table failed", - 204 : "Update display", - 205 : "Update display failed", - 206 : "Power unit", - 207 : "Bridge short-circuit", - 208 : "Execution (Watchdog)", - 209 : "24h watchdog test", - 210 : "Ethernet", - 211 : "Fan interior", - 212 : "Fan interior 2", - 213 : "Fan heat sink", - 214 : "Fan transformer", - 215 : "Fan transformer 2", - 216 : "Fan test", - 217 : "Residual current", - 218 : "High discharge current", - 219 : "Operating condition residual current", - 220 : "Residual current too high", - 221 : "Installation fault", - 222 : "Frequency monitoring", - 223 : "G83/1", - 224 : "Display self-test start message", - 225 : "Grid parameter unchanged", - 226 : "Changing of grid parameters not possible", - 228 : "Grid parameter locked", - 229 : "Grid monitoring", - 230 : "Grid measurements", - 231 : "Grid fault", - 232 : "Reconnection time upon grid interruption", - 233 : "Reconnection time upon short interruption", - 234 : "Maximum duration of a short interruption", - 235 : "Parallel grid operation", - 236 : "Reconnection time upon restart", - 237 : "N grid conn. at grid conn.pt.", - 238 : "Grid relay status", - 239 : "Set group", - 240 : "Condition", - 241 : "Device status", - 242 : "Median maximum threshold", - 243 : "Median maximum threshold tripping time", - 244 : "Overcurrent input C (HW)", - 245 : "Lower maximum threshold", - 246 : "Lower maximum threshold tripping time", - 247 : "G83/1-1", - 248 : "Air humidity", - 249 : "Wind direction", - 250 : "Wind speed", - 251 : "Heat sink", - 252 : "Heat sink 2", - 253 : "Hardware version", - 254 : "Grid frequency", - 255 : "End point of the power control via frequency", - 256 : "Start point of the power control via frequency", - 257 : "Frequency not permitted", - 258 : "Switching status grid relay", - 259 : "Operating condition grid frequency", - 260 : "HTTP", - 261 : "Derating occurred", - 262 : "Unstable operation", - 263 : "SMA grid guard code invalid", - 264 : "SMA grid guard code valid", - 265 : "GridGuard password", - 266 : "Interface", - 267 : "Inverter", - 268 : "Insulation monitoring", - 269 : "Data storage not possible", - 270 : "KEPCO guide", - 271 : "kB", - 272 : "Insulation resistance", - 273 : "Minimum insulation resistance", - 274 : "Operating condition insulation resistance", - 275 : "10 minute average", - 276 : "Instantaneous value", - 277 : "Derating", - 278 : "Upper minimum threshold", - 279 : "Upper minimum threshold tripping time", - 280 : "Byte", - 281 : "Median minimum threshold", - 282 : "Median minimum threshold tripping time", - 283 : "B", - 284 : "Device name", - 285 : "KEMCO501/2008", - 286 : "Device class", - 287 : "Upper maximum threshold", - 288 : "Upper maximum threshold tripping time", - 289 : "PV module", - 290 : "Measured values", - 291 : "Lower minimum threshold", - 292 : "Lower minimum threshold tripping time", - 294 : "Device type", - 295 : "MPP", - 296 : "Modem", - 297 : "Message", - 298 : "Name", - 299 : "Type Label", - 300 : "Nat", - 301 : "Grid failure", - 302 : "-------", - 303 : "Off", - 304 : "Island mode", - 305 : "Island mode", - 306 : "Island mode 60 Hz", - 307 : "Ok", - 308 : "On", - 309 : "Operation", - 310 : "Operating condition", - 311 : "Open", - 312 : "Phase assignment", - 313 : "Island mode 50 Hz", - 314 : "Maximum active power", - 315 : "Currently set active power limit", - 316 : "Operating mode Active power", - 317 : "All phases", - 318 : "Overload", - 319 : "Overtemperature", - 320 : "Varistor defective", - 321 : "Printed circuit board", - 322 : "PE connection missing", - 323 : "PE connection monitoring", - 324 : "L / N swapped", - 325 : "Phase L1", - 326 : "Phases L1, L2 and L3", - 327 : "Phase L2", - 328 : "Proxy settings", - 329 : "Phase L3", - 330 : "Port", - 331 : "Phase voltage", - 332 : "Operating condition voltage", - 333 : "PPC", - 334 : "Atmospheric pressure", - 335 : "Recommended action", - 336 : "Contact manufacturer", - 337 : "Contact installer", - 338 : "invalid", - 339 : "DC voltage control type", - 340 : "PV system", - 341 : "Recommended action", - 342 : "Production test mode", - 343 : "RD1663", - 344 : "Reset operating data", - 345 : "Controller", - 346 : "Remote control", - 347 : "Device restart triggered", - 348 : "Revision status", - 349 : "Grid relay closed", - 350 : "Waiting time until feed-in", - 351 : "Voltage increase protection", - 352 : "RD1663/661", - 353 : "Reset events", - 354 : "Reset maximum values", - 355 : "Reset energy logger", - 356 : "Reset operation inhibition", - 357 : "Number of Resets", - 358 : "SB 4000TL-20", - 359 : "SB 5000TL-20", - 360 : "Storage card", - 361 : "SD card defective", - 362 : "Reading SD Card", - 363 : "Parameter file not found or defective", - 364 : "Set parameter", - 365 : "Parameter setting failed", - 366 : "Parameters set successfully", - 367 : "No new update on the SD card", - 368 : "Update file defective", - 369 : "Update file OK", - 370 : "No update file found", - 372 : "Serial number", - 373 : "RD1663-A", - 374 : "Self diagnosis", - 375 : "self-test", - 376 : "Abort self-test", - 377 : "Number of S0 impulses", - 378 : "Consumed energy", - 379 : "Software version Update", - 380 : "Deactivation delay", - 381 : "Stop", - 382 : "Number of DC disconnects", - 383 : "Input A defective", - 384 : "Input B defective", - 385 : "Start delay", - 386 : "unclear", - 387 : "Critical voltage to start feed-in", - 388 : "Operation status", - 389 : "Startup status", - 390 : "Stop status", - 391 : "Cold start status", - 392 : "Test HW status", - 393 : "Software version", - 394 : "System", - 395 : "Temperature", - 396 : "Derating temperature", - 397 : "Operating condition temperatures", - 398 : "Time", - 399 : "Sensor fault fan permanently on", - 400 : "Temperature", - 401 : "Highest measured temperature", - 402 : "Phases L1 and L2", - 403 : "Phases L1 and L3", - 404 : "Phases L2 and L3", - 405 : "Set total time", - 406 : "Phase total Current", - 407 : "Operating condition current", - 408 : "Set operating time", - 409 : "Operating time", - 410 : "Set feed-in time", - 411 : "Feed-in time", - 412 : "Apparent power", - 413 : "Reactive power", - 414 : "Operating condition reactive power", - 416 : "Power", - 417 : "Absorbed energy", - 418 : "Total yield", - 419 : "Operating condition power", - 422 : "Transformer", - 423 : "Validation system", - 424 : "Update Bluetooth", - 425 : "Update Bluetooth failed", - 426 : "Update completed", - 427 : "Update main CPU", - 428 : "Update main CPU failed", - 429 : "Update RS485I module", - 430 : "Update RS485I module failed", - 431 : "Update communication", - 432 : "Update language table", - 433 : "Update language table failed", - 434 : "Update display", - 435 : "Update display failed", - 436 : "Apparent power", - 437 : "Reactive power", - 438 : "VDE0126-1-1", - 439 : "Special setting VDE0126-1-1", - 440 : "Manufacturer", - 441 : "Voltage", - 442 : "Voltage monitoring", - 443 : "Constant voltage", - 444 : "Voltage limit", - 445 : "Maximum voltage", - 446 : "Operating condition voltage", - 447 : "Voltage setpoint", - 448 : "Power per phase", - 449 : "Nominal voltage", - 450 : "Power", - 451 : "Operating condition power", - 452 : "Web service", - 455 : "Warning", - 456 : "Waiting for DC start conditions", - 457 : "Waiting for grid voltage", - 458 : "Sunny Central", - 459 : "Overcurrent, input in short-circuit (HW)", - 460 : "Sunny Boy", - 461 : "SMA", - 462 : "On-board supply sys. dist. 15V", - 463 : "Check DC generator", - 464 : "DC overvoltage (HW)", - 465 : "DC switch", - 466 : "DC overvoltage", - 467 : "DC overcurrent", - 468 : "Fault CAN Initialisation", - 469 : "Fault DA converter", - 470 : "Fault reverse current", - 471 : "Fault IPC communication", - 472 : "Fault RTC Initialization", - 473 : "Fault overvoltage protector", - 474 : "Ground fault detected", - 475 : "Frequent watchdog fault", - 476 : "Internal timing fault", - 477 : "Reverse current", - 478 : "Check inverter electronics", - 479 : "Check inv. electr. and comm.", - 480 : "Check inverter electr. and fan", - 481 : "Chk inv.electr. and contactors", - 482 : "Check inv.electr. and SW vers.", - 483 : "Communication fault CAN", - 484 : "Communication fault IPC", - 485 : "Fan fault", - 486 : "Fan fault interior", - 487 : "Fan fault interior 2", - 488 : "Fan fault heat sink", - 489 : "Fan fault heat sink 2", - 490 : "Fan fault motor prot. switch", - 491 : "Fan fault coilware", - 492 : "Fan fault coilware 2", - 493 : "Check grid and fuses", - 494 : "Check grid frequency", - 495 : "Maximum grid frequency disturbance", - 496 : "Maximum grid frequency disturbance", - 497 : "Minimum grid frequency disturbance", - 498 : "Minimum grid frequency disturbance", - 499 : "Check grid voltage", - 500 : "Grid overvoltage fast", - 501 : "Grid undervoltage fast", - 502 : "Smoke alarm", - 503 : "Fault sensor ambient temp.", - 504 : "Fault sensor battery temp.", - 505 : "Fault sensor DC voltage", - 506 : "Fault sensor pow.unit temp2", - 507 : "Fault sensor fan perm. on", - 508 : "Fault sensor transf. temp.", - 509 : "Synchronization error", - 510 : "Team switch", - 511 : "Overvoltage EVR (HW)", - 512 : "Overvoltage protector", - 513 : "Check overvoltage protector", - 514 : "Overcurrent EVR (HW)", - 515 : "Overtemperature outside", - 516 : "Overtemperature battery", - 517 : "Overtemperature EVR (HW)", - 518 : "Overtemp. power unit (HW)", - 519 : "Overtemperature power unit 2", - 520 : "Overtemp. transformer area", - 521 : "Overtemperature switch", - 522 : "Invalid device address", - 523 : "Invalid parameter file", - 524 : "Unspecified HW fault (HW)", - 525 : "Watchdog BFR", - 526 : "Watchdog DSP", - 527 : "Display self-test start mess.", - 528 : "Insolation", - 529 : "Insolation on external sensor", - 530 : "Set total yield", - 531 : "Set absorbed energy", - 532 : "Set highest measured temperature", - 533 : "Communication version", - 534 : "Generator control", - 535 : "String protection defective", - 536 : "DC converter string C defective", - 537 : "EvtTmpPwrLim", - 538 : "Grid impedance jump", - 539 : "EvtExlIn", - 540 : "Ground fuse missing", - 541 : "DC current sensor C offset", - 542 : "Internal meas. comp. fault", - 543 : "Internal meas. comp. fault", - 544 : "Internal meas. comp. fault", - 545 : "Internal meas. comp. fault", - 546 : "Meas. recording fault", - 547 : "Grid fault reported", - 548 : "Team relay defective", - 549 : "Team instable", - 550 : "Team config", - 551 : "Team coupling", - 552 : "Team disconnection", - 553 : "Team head config", - 554 : "Team error", - 555 : "Grid impedance too high", - 556 : "EvtGriOp", - 557 : "Temperature derating", - 558 : "SB 3000TL-20", - 559 : "VDE0126-1-1 B", - 560 : "EN50438", - 561 : "EN50438-CZ", - 562 : "C10/11", - 563 : "Day yield", - 564 : "Set number of grid connections", - 565 : "Power specif. via char. curve", - 566 : "Temporal control of the power limitation", - 567 : "Reset operating data (for Service)", - 568 : "Execute all", - 569 : "Activated", - 570 : "Execute write operation", - 571 : "Write events on memory card", - 572 : "Write faults to SD", - 577 : "Specific plant yield", - 578 : "Performance ratio", - 579 : "Revenue", - 580 : "CO2 avoidance", - 581 : "Specific inverter yield", - 582 : "Active power limitation", - 583 : "Checking firmware", - 584 : "Access Control", - 585 : "Parameter '%s' set successfully", - 586 : "Setting of parameter '%s' failed", - 587 : "Parameter '%s' set successfully", - 588 : "Setting of parameter '%s' failed", - 589 : "Parameter '%s' set successfully", - 590 : "Setting of parameter '%s' failed", - 591 : "Set user password", - 592 : "Set installer password", - 593 : "Set service password", - 594 : "Set developer password", - 595 : "Update successful", - 596 : "Update failed", - 597 : "Time adjusted / old time", - 598 : "Time adjusted / new time", - 599 : "Update to ver.|s0| successful", - 661 : "Minimum", - 662 : "Maximum", - 663 : "Sum", - 664 : "Average", - 665 : "Number of devices", - 666 : "Piece/yield", - 667 : "Minimum of lower limits", - 668 : "Maximum of lower limits", - 669 : "Minimum of upper limits", - 670 : "Maximum of upper limits", - 671 : "Minimum of current values", - 672 : "Maximum of current values", - 700 : "Hardware Interface 1", - 701 : "Hardware Interface 2", - 702 : "Hardware Interface 3", - 703 : "Time settings", - 704 : "Update", - 705 : "Device update", - 706 : "Status and Actions", - 707 : "User settings", - 708 : "Basic settings", - 709 : "SunnyDNS", - 710 : "FTP Push", - 711 : "FTP server", - 714 : "DNS server IP", - 715 : "Gateway IP", - 716 : "IP Address", - 717 : "Subnet mask", - 718 : "WAN IP", - 719 : "Internet service provider IP", - 722 : "Standard or Daylight Saving Time", - 724 : "Date format", - 725 : "Language", - 726 : "Unit of length", - 727 : "Number format", - 728 : "Unit of temperature", - 729 : "Time format", - 730 : "Standard/Daylight Saving Time conversion on", - 731 : "Automatic time synchronization", - 732 : "Time zone", - 733 : "Activated", - 734 : "Time interval", - 735 : "Login", - 736 : "Password", - 737 : "Server", - 738 : "Connection test", - 739 : "GPRS-APN", - 740 : "Dial-in number", - 741 : "Dial-in password", - 742 : "PIN", - 743 : "Signal strength test", - 744 : "Upload data", - 745 : "Result of the last upload", - 746 : "Portal connection test", - 747 : "Result of the last portal connection test", - 748 : "Register", - 749 : "Result of the last registration", - 750 : "Email", - 751 : "Plant name", - 752 : "Plant ID", - 753 : "Upload frequency", - 754 : "Write access allowed", - 755 : "GPRS-Always-On activated", - 766 : "DD.MM.YYYY", - 767 : "MM/DD/YYYY", - 768 : "YYYY.MM.DD", - 769 : "MM.DD.YYYY", - 770 : "DD/MM/YYYY", - 771 : "YYYY/MM/DD", - 772 : "DD-MM-YYYY", - 773 : "YYYY-MM-DD", - 774 : "MM-DD-YYYY", - 775 : "HH:mm", - 776 : "hh:mm", - 777 : "Deutsch", - 778 : "English", - 779 : "Italiano", - 780 : "Espanol", - 781 : "Francais", - 782 : "????????", - 783 : "???", - 784 : "Cesky", - 785 : "Portugues", - 786 : "Nederlands", - 787 : "123456.0", - 788 : "123456", - 789 : "123456", - 790 : "123,456.0", - 791 : "Celsius", - 792 : "Kelvin", - 793 : "Fahrenheit", - 794 : "Metric", - 795 : "Imperial", - 796 : "Slovenski", - 797 : "?????????", - 798 : "Polski", - 799 : "???", - 800 : "Disabled", - 801 : "???????", - 802 : "Active", - 803 : "Inactive", - 804 : "?????", - 805 : "HH:mm:ss", - 806 : "hh:mm:ss", - 830 : "Status", - 831 : "Type Label", - 832 : "Device", - 833 : "User Rights", - 834 : "DC Side", - 835 : "AC Side", - 836 : "Grid Monitoring", - 837 : "Generator", - 838 : "Battery", - 839 : "Plant Communication", - 840 : "External Communication", - 841 : "Data Recording", - 842 : "Sunny Portal", - 843 : "Further Applications", - 844 : "Meteorology", - 845 : "Theft Protection", - 846 : "Device Components", - 847 : "Equipment & device control system", - 861 : "User", - 862 : "Installer", - 863 : "Service", - 864 : "Developer", - 867 : "10MBit", - 868 : "100MBit", - 869 : "Bluetooth", - 870 : "Speedwire", - 871 : "Analog modem", - 872 : "GSM", - 873 : "Interface GPRS", - 874 : "UMTS", - 875 : "Software package", - 876 : "Total yield logger partially deleted", - 877 : "Find device", - 878 : "LED blinking", - 879 : "Components", - 880 : "SUSyID", - 881 : "Sunny Explorer", - 882 : "Plant name", - 883 : "Time difference Plant/System", - 884 : "not active", - 885 : "none", - 886 : "none", - 887 : "none", - 888 : "Current event", - 889 : "Bluetooth", - 890 : "Power absorbed", - 891 : "WebBox-20", - 892 : "String failure detection", - 893 : "Signal processor update", - 894 : "Signal processor update failed", - 900 : "Central assembly", - 901 : "Communication assembly", - 902 : "Residual current monitoring unit", - 903 : "Display", - 904 : "Logic component", - 905 : "RS485 module", - 906 : "Zigbee components", - 907 : "Bluetooth component", - 908 : "Operating system", - 909 : "String protection", - 910 : "Protocol converter", - 911 : "Module shaft 1", - 912 : "Webconnect module", - 913 : "Power control modules", - 914 : "Module shaft 2", - 932 : "Initialization Start: |tn0|", - 933 : "Initialization End: |tn0|", - 934 : "Operation Start: |tn0|", - 935 : "Operation End: |tn0|", - 936 : "Shutdown Start: |tn0|", - 937 : "Shutdown End: |tn0|", - 938 : "Internal fault 0x|x4||x5||x6||x7|/|u0|", - 939 : "Calculation overflow in module |u0|", - 940 : "Startup |x5|:|x4|:|x3|:|x2|:|x1|:|x0|:|5u8|", - 941 : "Resource |s0| could not load.", - 942 : "Server could not start|x5|:|x4|:|x3|:|x2|:|x1|:|x0|:|5u8|", - 943 : "24h Timeout at parameter setting |ln8c|", - 944 : "Login OK: Level: |u8|Device: |x1||x0||x7||x6||x5||x4|", - 945 : "Logout: Level: |u8|Device:|x1||x0||x7||x6||x5||x4|", - 946 : "Auth. error: Level: |u8|Device: |x1||x0||x7||x6||x5||x4|", - 947 : "Login error: Level: |u8|Device: |x1||x0||x7||x6||x5||x4|Error: |dc|", - 948 : "Detection started", - 949 : "New Device: |x1||x0||x7||x6||x5||x4|", - 950 : "Rec. Hello World: Device: |x1||x0||x7||x6||x5||x4|", - 951 : "Sent Hello World", - 952 : "New Object Unknown: Device: |x1||x0| |x7||x6||x5||x4| - |x9||x8|", - 953 : "New Master: Device: |x1||x0||x7||x6||x5||x4|", - 954 : "Login started: Level: |u0|", - 955 : "Login End: Level: |u0|", - 956 : "Logout started: Level: |u0|", - 957 : "Bluetooth connection to root node established", - 958 : "Bluetooth connection to root node terminated", - 959 : "Bluetooth connection has broken", - 960 : "New dev.info ['|x5|:|x4|:|x3|:|x2|:|x1|:|x0|'], Type", - 961 : "Conn.device ['|x5|:|x4|:|x3|:|x2|:|x1|:|x0|'] lost", - 962 : "BCN: Radio network established", - 963 : "Server prob. not available until |s0| due to maint", - 964 : "Server not available: |d0|", - 965 : "Registration failed |d0|", - 966 : "|d0| bytes successfully transmitted in |d4| sec.", - 967 : "Data succ. transmitted: |d0| bytes in |d4| seconds", - 968 : "Data transm. aborted after |d0| bytes and |d4| sec. flt: |d8|", - 969 : "Time synchronization failed |d0|", - 970 : "Faulty parameter '%s'", - 971 : "Internal ODB fault |d0|", - 972 : "Ensure DC supply", - 973 : "------", - 974 : "String protection", - 975 : "Restart Learning", - 976 : "Reverse currents or substring |s0| polarity rev.", - 977 : "Substring |s0| failed", - 978 : "ESS-IGBT defective Input |s0|", - 979 : "ESS Relay fault Input |s0|", - 980 : "Relay control defective input |s0|", - 981 : "HSS-IGBT defective input |s0|", - 982 : "Ring line interrupted", - 983 : "Short-circuit String A, risk of arc.Don't pull ESS", - 984 : "Arcing danger DC plug input; reinsert ESS", - 985 : "Varistor A or B through thermal fuse", - 986 : "Varistor A or B through arcing", - 987 : "Lightning protection device at input A defective", - 988 : "Overheating", - 989 : "String |s0| defective", - 990 : "String |s0| defective", - 991 : "Lightning protection inactive", - 992 : "Overheating", - 993 : "Reverse currents or input |s0| polarity reversed", - 994 : "Phase(s) or neutral conductor not connected", - 995 : "Do not disconnect ESS", - 996 : "Connect ESS, do not open cover", - 997 : "Check varistors", - 998 : "Check lightning protector A/PE", - 999 : "Disconnect device from generator and grid", - 1000 : "New device cannot be administered: Device: |x1||x0| |x7||x6||x5||x4|", - 1001 : "Parameter |ln8c| was sent", - 1002 : "Bluetooth Repeater", - 1003 : "Intermediate circuit voltages not permitted", - 1004 : "Grid type detection failed", - 1005 : "Grid current sensor defective", - 1006 : "General fault", - 1007 : "Overcurrent Ground fuse", - 1008 : "MSD", - 1009 : "G77", - 1010 : "AGL", - 1011 : "UL1741", - 1012 : "UL1741/2005", - 1013 : "Other standard", - 1014 : "DK5950", - 1015 : "UL1741/2001", - 1016 : "Constant current", - 1017 : "PEA", - 1018 : "MEA", - 1020 : "Medium-Voltage Directive (Germany)", - 1021 : "Airdolphine", - 1022 : "Operating mode of static voltage stabilisation", - 1023 : "Operating mode active power red., overfreq. P(f)", - 1024 : "Configuration of static voltage stabilization", - 1025 : "Config. reactive power/voltage charact. curve Q(U)", - 1026 : "Voltage difference to next charact. curve value", - 1027 : "Time to adoption of next charact. curve value", - 1028 : "Nominal voltage offset", - 1029 : "Reactive power gradient", - 1030 : "Stop voltage", - 1031 : "Reactive power setpoint Q", - 1032 : "MVtgDirective Internal", - 1033 : "Configuration of reactive power mode Q(P)", - 1034 : "Reactive power value starting point", - 1035 : "Active power value starting point", - 1036 : "Reactive power value end point", - 1037 : "Active power value end point", - 1038 : "Configuration of cosPhi, direct specification", - 1039 : "cosPhi specification", - 1040 : "Excitation type of cosPhi", - 1041 : "Overexcited", - 1042 : "Underexcited", - 1043 : "Configuration of cosPhi(P) characteristic", - 1044 : "Excitation type at starting point", - 1045 : "cosPhi of start point", - 1046 : "Excitation type at end point", - 1047 : "cosPhi of end point", - 1048 : "Configuration of feed-in management", - 1049 : "Configuration of active power P limitation", - 1050 : "Power per phase", - 1051 : "Reference value for normalized active power", - 1052 : "Config. active power reduct. at overfrequency P(f)", - 1053 : "Config. of linear instantaneous power gradient", - 1054 : "Difference between starting freq. and grid freq.", - 1055 : "Active power gradient", - 1056 : "Difference between reset frequency and grid freq.", - 1057 : "Activation of stay-set indicator function", - 1058 : "Synchronize time with portal", - 1059 : "Current reactive power limit", - 1060 : "Max. reactive power", - 1061 : "Currently set apparent power limit", - 1062 : "Maximum apparent power", - 1063 : "Current cosPhi limit", - 1064 : "Min. cosPhi", - 1065 : "Power gradient for reconnection after grid fault", - 1066 : "Curr. active power grad., reconnection, grid fault", - 1067 : "Config. of reactive power Q, direct specification", - 1068 : "Activation of active power gradient", - 1069 : "React. power/volt. char. Q(U)", - 1070 : "Reactive power Q, direct spec.", - 1071 : "React. power const. Q in kvar", - 1072 : "Q specified by plant control", - 1073 : "Reactive power Q(P)", - 1074 : "cosPhi, direct specific.", - 1075 : "cosPhi, specified by plant control", - 1076 : "cosPhi(P) characteristic", - 1077 : "Active power limitation P in W", - 1078 : "Act. power lim. as % of Pmax", - 1079 : "Act. power lim. via plant ctrl", - 1080 : "Plant control", - 1081 : "AC circuit breaker activated or open", - 1082 : "Installation failure grid connection", - 1083 : "Check grid and rotating field", - 1084 : "Rotating field left", - 1085 : "Primary Master", - 1086 : "Secondary Master", - 1087 : "Device control", - 1088 : "Data inconsistency", - 1089 : "AC bridge not ready for operation", - 1090 : "UCE monitoring HF half-bridge", - 1091 : "Bridge short circuit HF half-bridge", - 1092 : "Voltage conditions not met", - 1093 : "Fault sensor PCB temperature", - 1094 : "External fan fault", - 1095 : "Boost converter", - 1096 : "Boost converter 2", - 1097 : "Maximum phase shift", - 1098 : "Tripping time for max. phase shift", - 1099 : "Max. frequency change per second", - 1100 : "Tripping time for max. frequency change per second", - 1101 : "Lower reconnection limit", - 1102 : "Upper limit for reconnection", - 1103 : "Nominal frequency", - 1104 : "Normalized total apparent power", - 1105 : "Boost converter", - 1106 : "Overtemperature boost converter", - 1107 : "Frequency change not permitted", - 1108 : "Calibration voltage", - 1109 : "Calibration status", - 1110 : "AC voltage calibration failed", - 1111 : "Failed", - 1112 : "Not executed", - 1113 : "Ground fuse fault", - 1114 : "Check ground fuse", - 1115 : "Replace fan", - 1116 : "Clean fan", - 1117 : "Varistor monitoring defective", - 1118 : "Calibration failed", - 1119 : "Selection of the voltage(s) to be calibrated", - 1120 : "Maximum ground current", - 1121 : "Tripping time maximum ground current", - 1122 : "Grounding prescribed?", - 1123 : "Prescribed grounding type", - 1124 : "Grounding status", - 1125 : "Positive", - 1126 : "Negative", - 1127 : "No grounding", - 1128 : "None prescribed", - 1129 : "Yes", - 1130 : "No", - 1131 : "Grid relay open", - 1132 : "Linear gradient", - 1133 : "Configuration of reactive power mode const. Q as %", - 1134 : "Configuration of active power mode const. W as %", - 1135 : "Update string prot. failed", - 1136 : "Update string prot. failed", - 1137 : "Update string protection", - 1138 : "Update string protection", - 1139 : "UL1741/2005, 208 V", - 1140 : "UL1741/2005, 240 V", - 1141 : "Grounding error", - 1142 : "Wrong earthing type", - 1143 : "Wrong earthing type; check earthing set", - 1144 : "Set plant time", - 1145 : "Use Sunny Portal", - 1146 : "Execute", - 1147 : "Not initialized", - 1148 : "Not connected", - 1149 : "Searching", - 1150 : "Not connected", - 1151 : "Connected", - 1152 : "Not connected", - 1153 : "Not connected", - 1154 : "Firmware update completed", - 1163 : "Zigbee", - 1164 : "Bluetooth", - 1165 : "Ethernet", - 1166 : "Serial", - 1167 : "Speedwire", - 1170 : "Downlink", - 1171 : "Uplink", - 1173 : "Current root node", - 1174 : "Possible root nodes", - 1175 : "Connection quality", - 1176 : "Status", - 1177 : "Fault indication", - 1179 : "NetID", - 1180 : "Current event", - 1186 : "DC current measurement defective", - 1187 : "every 15 minutes", - 1188 : "hourly", - 1189 : "daily", - 1190 : "Syslog service", - 1191 : "Activated until", - 1192 : "Config. reactive power mode of plant control", - 1193 : "Configuration of active power mode of plant ctrl", - 1194 : "cosPhi config. method of plant control", - 1195 : "Time-out for communication fault indication", - 1196 : "Export", - 1197 : "Measurement name in local language", - 1198 : "Events in local language", - 1199 : "PPDS", - 1200 : "String protection OK", - 1201 : "OptiTrac Global Peak", - 1202 : "Cycle time", - 1203 : "Power limit", - 1204 : "Setpoint for PV voltage", - 1205 : "Reference voltage", - 1206 : "Setpoint for intermediate circuit voltage", - 1207 : "Update file", - 1208 : "Adaptor: Conn. interrupted", - 1209 : "Adapter event: NetID changed", - 1210 : "Not connected", - 1211 : "Not connected", - 1212 : "Not connected", - 1213 : "DAA type ID", - 1214 : "RAA type ID", - 1215 : "Time interval expired", - 1216 : "Dynamic settings established", - 1217 : "Hysteresis voltage", - 1218 : "Gradient K of reactive current droop", - 1219 : "Specified voltage UQ0", - 1220 : "Symmetrical limit for maximum reactive power", - 1221 : "PWM reverse voltage", - 1222 : "Reactive power gradient", - 1223 : "Adjustment time for charact. curve operating point", - 1224 : "Active power at starting point", - 1225 : "Active power at end point", - 1226 : "Reference correction voltage", - 1227 : "PWM inverse voltage", - 1228 : "PWM inversion delay", - 1229 : "Reactive current droop", - 1230 : "Configuration of dynamic grid support", - 1231 : "NetID changed: New ID: |x3||x2||x1||x0|", - 1232 : "Check for update and install it", - 1233 : "SDLWindV", - 1234 : "Diagnosis", - 1235 : "CPU monitor", - 1236 : "CPU load", - 1237 : "Server path", - 1238 : "Update started", - 1239 : "Search for update completed successfully", - 1240 : "Search for update not compl. successfully: |tn0|", - 1241 : "Update aborted", - 1242 : "Download of an update started", - 1243 : "Download of an update completed successfully", - 1244 : "Download of update not compl. successfully: |tn0|", - 1245 : "Version unknown", - 1246 : "Incorrect package size", - 1247 : "One or more parameters are missing", - 1248 : "Next connection", - 1249 : "Next connection 2", - 1250 : "Next connection 3", - 1251 : "IRE status", - 1252 : "Adaptor event: Conn. restored", - 1253 : "Lower limit, voltage dead band", - 1254 : "Upper limit, voltage dead band", - 1255 : "Grid voltage fault", - 1256 : "Update Speedwire", - 1257 : "Update Speedwire", - 1258 : "Result of the last connection test", - 1259 : "Short-circuit String B, risk of arc.Don't pull ESS", - 1260 : "Lightning protection device at input B defective", - 1261 : "Check lightning protector B/PE", - 1262 : "Configuration of full dynamic grid support", - 1263 : "Operating mode of dynamic grid support", - 1264 : "Full dynamic grid support", - 1265 : "Limited dynamic grid support", - 1266 : "mA", - 1267 : "km/h", - 1268 : "mph", - 1269 : "kOhm", - 1270 : "mOhm", - 1271 : "mV", - 1272 : "kVA", - 1273 : "kvar", - 1274 : "kW/m2", - 1275 : "kW", - 1276 : "MW", - 1277 : "GW", - 1278 : "MWh", - 1279 : "GWh", - 1280 : "Ws", - 1281 : "g", - 1282 : "kg", - 1283 : "lb.", - 1284 : "t", - 1285 : "m2", - 1286 : "sq.ft.", - 1287 : "m", - 1288 : "km", - 1289 : "ft.", - 1290 : "g/kWh", - 1291 : "kg/kWh", - 1292 : "kWh/kWp", - 1293 : "Ah", - 1294 : "As", - 1296 : "New update available: Version |s0|", - 1297 : "FTP Push connection test successfully completed.", - 1298 : "An error occurred in the FTP Push conn. test: |s0|", - 1299 : "FTP server started.", - 1300 : "FTP server stopped.", - 1301 : "An error occurred when start. the FTP server: |s0|", - 1302 : "An error occurred when stop. the FTP server: |s0|", - 1303 : "FTP upload completed.", - 1304 : "An error occurred during the FTP upload: |s0|", - 1305 : "Learning", - 1306 : "Update Speedwire module failed", - 1307 : "Server not available", - 1308 : "Registration failed: |tn0|", - 1309 : "Time synchronization failed: |tn0|", - 1310 : "Data transmission aborted: |tn0|", - 1311 : "Unknown device class", - 1312 : "System fault", - 1313 : "Authentication fault", - 1314 : "Web service not available", - 1315 : "Sunny WebBox not registered with the Sunny Portal", - 1316 : "Update version of the software package", - 1317 : "Automatic update", - 1318 : "Time of the automatic update", - 1319 : "No version available", - 1320 : "Identification of WAN IP via Sunny Portal failed", - 1321 : "Measures in the case of a grounding error", - 1322 : "Disconnect from grid", - 1323 : "Warn", - 1324 : "Server not available: |lv04|", - 1325 : "Data export in CSV format", - 1326 : "Data export in XML format", - 1327 : "Displacement power factor", - 1328 : "Reactive power droop mode", - 1329 : "Voltage spread", - 1330 : "Hysteresis", - 1331 : "Dead band", - 1332 : "Frequency monitoring", - 1333 : "Unbalance detection", - 1334 : "Permissible grid unbalance", - 1335 : "Tripping time of the unbalance detection", - 1336 : "Tripping time of the frequency monitor", - 1337 : "UL1741/120", - 1338 : "UL1741/208", - 1339 : "UL1741/240", - 1340 : "Multifunction relay", - 1341 : "Fault indication", - 1342 : "Fan control", - 1343 : "Self-consumption", - 1344 : "Minimum On time", - 1345 : "Minimum On power", - 1346 : "Minimum power On time", - 1347 : "Operating mode", - 1348 : "Initiate device restart", - 1349 : "Control via communication", - 1350 : "Configuration of 'Turbine' operating mode", - 1351 : "Constant deviation of power calculation", - 1352 : "Coefficient of power calculation based on Udc", - 1353 : "Coefficient of power calculation based on Udc^2", - 1354 : "Coefficient of power calculation based on Udc^3", - 1355 : "Proportional factor of power control", - 1356 : "Integral factor of power control", - 1357 : "Differential factor of power control", - 1358 : "Critical voltage to end feed-in", - 1359 : "Battery bank", - 1360 : "Minimum time before reconnection", - 1361 : "0,001", - 1362 : "0,000001", - 1363 : "Rate for feed-in reimbursement", - 1364 : "Rate for self-use reimbursement", - 1365 : "Electricity tariff", - 1366 : "Feed-in reimbursement", - 1367 : "Self-use reimbursement", - 1368 : "Electricity costs", - 1369 : "Login prescribed", - 1370 : "Transformer prot. triggered", - 1371 : "Quick stop triggered", - 1372 : "CAN communication fault", - 1374 : "AC separating point", - 1376 : "Invalid analogue active power specification", - 1377 : "Invalid digital active power specification", - 1378 : "Invalid analogue reactive power specification", - 1379 : "Invalid analogue power factor specification", - 1380 : "Doors have been opened during operation", - 1387 : "Reactive power Q, specific. via analogue input", - 1388 : "cosPhi specific. analog input", - 1389 : "Reactive power/volt. char. Q(U) param.", - 1390 : "Active power limitation P via analogue input", - 1391 : "Active power limitation P via digital inputs", - 1392 : "Fault", - 1393 : "Waiting for PV voltage", - 1394 : "Waiting for valid AC grid", - 1395 : "DC range", - 1396 : "AC grid", - 1397 : "Check active and reactive power interface", - 1398 : "Close doors and cancel release", - 1399 : "Check external transformer", - 1400 : "DC overvoltage peak", - 1401 : "Displacement power factor", - 1402 : "Excitation type of cosPhi", - 1403 : "Energy counter type", - 1404 : "PV generation counter", - 1405 : "Grid feed-in counter", - 1406 : "Grid reference counter", - 1407 : "PV plant measurements", - 1408 : "Supplied power", - 1409 : "Frequency threshold", - 1410 : "Grip impedance monitoring", - 1411 : "Current amplitude", - 1412 : "Max. impedance gradient", - 1413 : "Periodic AID", - 1414 : "Amplitude", - 1415 : "Normalized upper threshold", - 1416 : "Normalized lower threshold", - 1417 : "Norm. max. reconnection threshold", - 1418 : "Norm. min. reconnection threshold", - 1419 : "Specific CO2 reduction", - 1420 : "Grid type", - 1421 : "Impedance", - 1422 : "Centre point of P-coordinate", - 1423 : "Centre point of U-coordinate", - 1424 : "End point of U-coordinate", - 1425 : "Start point of U-coordinate", - 1426 : "Ripple control signal detection", - 1427 : "Ground voltage", - 1428 : "Backup mode operating mode", - 1429 : "Backup mode status", - 1430 : "PowerBalancer", - 1431 : "PowerGuard", - 1432 : "Power max. Value", - 1433 : "277 Volt", - 1434 : "208 Volt", - 1435 : "240 Volt", - 1436 : "208 Volt without neutral conductor", - 1437 : "240 Volt without neutral conductor", - 1438 : "Automatic", - 1439 : "In all phases", - 1440 : "Grid mode", - 1441 : "Separate network mode", - 1442 : "PhaseGuard", - 1443 : "PowerGuard", - 1444 : "FaultGuard", - 1445 : "Passive AID", - 1446 : "GridGuard-Version", - 1447 : "S0-pulse feed-in", - 1448 : "S0-pulse reference", - 1449 : "Insulation failure ignored", - 1450 : "Grounding error ignored", - 1451 : "Insulation monitoring configuration error", - 1452 : "No Remote GFDI response", - 1453 : "Permanent insulation failure", - 1454 : "Soft grounding triggered", - 1455 : "Emergency OFF", - 1456 : "Consumption", - 1457 : "Internal consumption increase", - 1458 : "Rise in self-consumption today", - 1459 : "PV mains connection", - 1460 : "Power supply status", - 1461 : "Mains connected", - 1462 : "Backup not available", - 1463 : "Backup", - 1464 : "Rated capacity throughput", - 1465 : "Lower battery charge limit", - 1466 : "Wait", - 1467 : "Start", - 1468 : "MPP search", - 1469 : "Shut down", - 1470 : "Fault", - 1471 : "Warning/error mail OK", - 1472 : "Warning/error mail not OK", - 1473 : "System info mail OK", - 1474 : "System info mail not OK", - 1475 : "Error mail OK", - 1476 : "Error mail not OK", - 1477 : "Warning mail OK", - 1478 : "Warning mail not OK", - 1479 : "Wait after mains interruption", - 1480 : "Waiting for utilities company", - 1481 : "Sunny central control", - 1482 : "Plant is not available in the portal", - 1483 : "Device is already available in the portal", - 1484 : "Invalid parameter was transmitted", - 1485 : "Unknown device version", - 1486 : "No rights to execute the operation", - 1487 : "Device successfully registered in the portal", - 1488 : "SSM Id for which comm. fault has occurred", - 1489 : "SMU warning code for string fault", - 1490 : "Status of signal contact 1", - 1491 : "Status of signal contact 2", - 1492 : "String temporarily deselected due to earth fault", - 1493 : "String permanently deselected due to earth fault", - 1494 : "Eliminate earth fault", - 1495 : "String detected w. yield loss", - 1496 : "Check functionality of the whole string", - 1497 : "Watchdog SMID CONT", - 1498 : "Watchdog SMID CT", - 1499 : "On-board supply sys. dist. 12V", - 1500 : "Replace SD card with a functional one", - 1501 : "Transmission attempts", - 1502 : "Time of the last transmission attempt", - 1503 : "Update source", - 1504 : "Automatic update", - 1505 : "Manual update", - 1506 : "Update portal", - 1507 : "Information", - 1508 : "90% of DC switch. cycl. reach.", - 1509 : "100% of DC switch. cyc. reach.", - 1510 : "Compress", - 1511 : "Compress and delete", - 1512 : "The data export to the SD card was temporarily deactivated as at least one update file is on the SD card.", - 1513 : "The data export to the SD card was re-activated.", - 1514 : "The firmware update with version number |u/9/0| for device type |tn4| was sent to the plant.", - 1515 : "The firmware update with version number |u/9/0| for device types |tn4| and |tn8| was sent to the plant.", - 1516 : "The firmware update with version number |u/9/0| for device types |tn4|, |tn8| and |tnc| was sent to the plant.", - 1517 : "The device with serial number |u0| was successfully updated to firmware version |u/9/4|.", - 1518 : "The device with serial number |u0| could not be updated to firmware version |u/9/4|.", - 1519 : "The device with serial number |u0| and firmware version |u/9/4| is no longer considered for the current update process as this appliance update has failed several times.", - 1520 : "Download of the update file with version |u/9/0| for device type |tn4| did not complete successfully.", - 1521 : "Download of the update file with version |u/9/0| for device types |tn4| and |tn8| did not complete successfully.", - 1522 : "Download of the update file with version |u/9/0| for device types |tn4|, |tn8| and |tnc| did not complete successfully.", - 1523 : "Wait for update conditions", - 1524 : "S0 pulses per infed kWh", - 1525 : "S0 pulses per consumed kWh", - 1526 : "Target version of the software package", - 1527 : "Force", - 1528 : "Reconnection fault grid", - 1529 : "Reconnection condition not satisfied", - 1530 : "208V WYE", - 1531 : "Grid switch", - 1532 : "Status after loss of communication in autom. mode", - 1533 : "Status after switching on automatic", - 1535 : "Jet offline test", - 1536 : "Timeout after loss of communication", - 1537 : "Starting current detection", - 1538 : "Gradient K of the reactive current droop", - 1539 : "Automatic mode can be activated", - 1540 : "Quick stop", - 1541 : "Unspecif. DSP fault", - 1542 : "Unspecif. BFR fault", - 1543 : "Overtemperature DC clamps", - 1544 : "A DC switch does not close", - 1545 : "Insulation failure stack", - 1546 : "Warning grounding error", - 1547 : "Permanent grounding error", - 1548 : "Warning softgrounding activated", - 1549 : "Permanent softgrounding error", - 1550 : "Softgrounding ignored", - 1551 : "Softgrounding hardware fault", - 1552 : "Warning insulation failure", - 1553 : "Do not change", - 1554 : "Disturbance sensor display temperature", - 1555 : "No display", - 1556 : "Display fault (temp. too low)", - 1557 : "Display fault (unknown display type)", - 1558 : "Display fault (display not connected)", - 1559 : "Run update", - 1560 : "Remote control disconnection active", - 1562 : "Phase L1 against L2", - 1563 : "Offset to AC current", - 1564 : "K1", - 1565 : "K1+K2", - 1566 : "K1+K2+K3", - 1567 : "K1+K2+K3+K4", - 1568 : "K1+K2+K4", - 1569 : "K1+K3", - 1570 : "K1+K3+K4", - 1571 : "K1+K4", - 1572 : "K2", - 1573 : "K2+K3", - 1574 : "K2+K3+K4", - 1575 : "K2+K4", - 1576 : "K3", - 1577 : "K3+K4", - 1578 : "K4", - 1579 : "Restart in |u0| seconds", - 1580 : "Please connect AC and DC", - 1581 : "Feeding", - 1582 : "Reset measured values", - 1583 : "Current flow direction", - 1584 : "Positive", - 1585 : "Negative", - 1586 : "Sunny portal occupied", - 1587 : "Network fault", - 1588 : "Reactive power specification", - 1589 : "cosPhi specification", - 1590 : "Active special functionality", - 1591 : "Control of wireless sockets", - 1592 : "Overtemperature throttle range", - 1593 : "Update file successfully copied", - 1594 : "The passwords of the device reset to factory s.", - 1595 : "Network settings of device reset to the factory s.", - 1596 : "The device has been reset to the factory setting", - 1597 : "The memory card is full or write-protected", - 1598 : "Transformer incorrectly connected", - 1599 : "Grid disconnection at 0% specification", - 1600 : "Conf. of the plant control procedure P(U)", - 1601 : "Characteristic curve number", - 1602 : "Conf. of the grid integr. characteristic curves", - 1603 : "Characteristic 1", - 1604 : "Adjustm. time characteristic curve operating point", - 1605 : "Decrease ramp", - 1606 : "Increase ramp", - 1607 : "Number of points to be used", - 1608 : "X value 1", - 1609 : "Y value 1", - 1610 : "X value 2", - 1611 : "Y value 2", - 1612 : "X value 3", - 1613 : "Y value 3", - 1614 : "X value 4", - 1615 : "Y value 4", - 1616 : "X value 5", - 1617 : "Y value 5", - 1618 : "X value 6", - 1619 : "Y value 6", - 1620 : "Active power gradient after reset frequency", - 1621 : "Active power gradient connection", - 1623 : "Root node", - 1624 : "Password recovery failed: Device: |u4|", - 1625 : "Sunny Portal", - 1626 : "NTP server", - 1627 : "Alarm", - 1628 : "Modbus", - 1629 : "TCP server", - 1630 : "UDP server", - 1631 : "DHCP server", - 1632 : "Repeated notification", - 1633 : "Email address(es)", - 1634 : "Send test e-mail", - 1635 : "Upload interval", - 1636 : "Start IP address", - 1637 : "End IP address", - 1638 : "Time synchronisation source", - 1639 : "Inputs/outputs", - 1640 : "Digital input group 1 (DI1 .. DI4)", - 1641 : "Digital input group 2 (DI5 .. DI8)", - 1642 : "Analogue current input 1", - 1643 : "Analogue current input 2", - 1644 : "Analogue current input 3", - 1645 : "Analogue voltage input 1", - 1646 : "Remaining space", - 1647 : "Detect string failures", - 1648 : "Detect partial string failures", - 1649 : "String |s0| low power", - 1650 : "Partial string |s0| low power", - 1651 : "Overvoltage suppression", - 1652 : "Minimum power reduction", - 1653 : "Sensor fault", - 1654 : "Offset DCinAC defective", - 1655 : "Electric arc detected", - 1656 : "Serial el.arc in String |s0| detected by AFCI mod.", - 1657 : "AFCI self-test failed", - 1658 : "AFCI self-test successful", - 1659 : "Knock to reset", - 1660 : "AFCI switched on", - 1661 : "Status: |tn0| / |tn4| / |tn8|", - 1662 : "Measuring interface 1", - 1663 : "Measuring interface 2", - 1664 : "Measuring interface 3", - 1665 : "Connection point", - 1666 : "Type of counter", - 1667 : "S0 reference", - 1668 : "S0 feed-in", - 1669 : "D0 reference", - 1670 : "D0 feed-in", - 1671 : "D0 reference and feed-in", - 1672 : "Activate island mode", - 1673 : "Not enough energy available from wind generator", - 1674 : "IsNotLogin response: Device: |x1||x0| |x7||x6||x5||x4|", - 1675 : "Login status response: Device: |x1||x0| |x7||x6||x5||x4|, status: |xb||xa||x9||x8|", - 1676 : "IsNotLogin query started", - 1677 : "LoginStatus query started", - 1678 : "Devices LoginStatus query: Device: |x1||x0| |x7||x6||x5||x4|", - 1679 : "Devices Login started: Device: |x1||x0| |x7||x6||x5||x4|, Level: |u8|", - 1680 : "Devices Logout started: Device: |x1||x0| |x7||x6||x5||x4|, Level: |xb||xa||x9||x8|", - 1681 : "MandatoryData queried: Device: |x1||x0| |x7||x6||x5||x4|, Obj: |x9||x8|, LRI: |xf||xe||xd||xc|", - 1682 : "Minimum insolation", - 1683 : "Maximum insolation", - 1684 : "Minimum measurement", - 1685 : "Maximum measurement", - 1686 : "Insolation sensor", - 1687 : "USB connection", - 1688 : "USB connection 2", - 1689 : "Energy absorbed today", - 1690 : "Fast shut-down", - 1691 : "Type", - 1692 : "String deactivated due to WMax", - 1693 : "No string connected", - 1694 : "DC switch tripped", - 1695 : "DC switch waits for connection", - 1696 : "DC switch blocked by spindle", - 1697 : "DC switch manually blocked", - 1698 : "DC switch 3 x tripped", - 1699 : "DC switch defective", - 1700 : "Key switch", - 1701 : "Local time", - 1702 : "DC switch", - 1703 : "String status", - 1704 : "Derating due to temperature", - 1705 : "Derating due to frequency", - 1706 : "Derating due to PV current", - 1707 : "SMA radio socket has switched to the status Automatic", - 1708 : "Speedwire", - 1709 : "SMACOM A", - 1710 : "SMACOM B", - 1711 : "Connection speed", - 1712 : "Current IP address", - 1713 : "Current subnet mask", - 1714 : "Current gateway address", - 1715 : "Current DNS server address", - 1716 : "Webconnect", - 1717 : "MAC address", - 1718 : "Automatic configuration switched on", - 1719 : "Faulty communication", - 1720 : "10 Mbit/s", - 1721 : "100 Mbit/s", - 1722 : "IRE faulty", - 1723 : "Supplied power (calculated)", - 1724 : "Counter status generation counter (calculated)", - 1725 : "No connection", - 1726 : "Half duplex", - 1727 : "Full duplex", - 1728 : "Duplex mode", - 1729 : "Communication error power unit", - 1730 : "Battery values", - 1731 : "Energy absorbed charge amount", - 1732 : "Charge amount released", - 1733 : "Charge", - 1734 : "Active charging process", - 1735 : "Maintenance", - 1736 : "Full and compensation charge", - 1737 : "Charging status", - 1738 : "Absorbed energy", - 1739 : "Energy released", - 1740 : "Generator", - 1741 : "Automatic start", - 1742 : "Reason for requesting generator", - 1743 : "Generator measured values", - 1744 : "Manual control", - 1745 : "Generator queries charge level", - 1746 : "Switch-off limit in time range 1", - 1747 : "Switch-off limit in time range 2", - 1748 : "Number of starts", - 1749 : "Full stop", - 1750 : "Current rise in self-consumption", - 1751 : "Current self-consumption", - 1752 : "Current capacity", - 1753 : "Time for quick charge", - 1754 : "Time for compensation charge", - 1755 : "Time for full charge", - 1756 : "Maximum start attempts after error", - 1757 : "Maximum charging current", - 1758 : "Current set charging voltage", - 1759 : "Nominal capacity", - 1760 : "Maximum temperature", - 1761 : "Nominal current", - 1762 : "Generator request via power", - 1763 : "Switch-off power", - 1764 : "Switch-on power", - 1765 : "Operating status", - 1766 : "Rise in self-consumption switched on", - 1767 : "Quick charge", - 1768 : "Full charge", - 1769 : "Compensation charge", - 1770 : "Maintenance charge", - 1771 : "Charge with solar power", - 1772 : "Charge w. solar a. mains power", - 1773 : "No request", - 1774 : "Load", - 1775 : "Time control", - 1776 : "Manual one hour", - 1777 : "Manual start", - 1778 : "External source", - 1779 : "Separated", - 1780 : "Public electricity mains", - 1781 : "Island mains", - 1782 : "Sealed lead battery (VRLA)", - 1783 : "Flooded lead acid batt. (FLA)", - 1784 : "Nickel/Cadmium (NiCd)", - 1785 : "Lithium-Ion (Li-Ion)", - 1787 : "Initialisation", - 1788 : "Ready", - 1789 : "Warming", - 1790 : "Synchronisation", - 1791 : "Activated", - 1792 : "Resynchronisation", - 1793 : "Generator separation", - 1794 : "Slow down", - 1795 : "Bolted", - 1796 : "Blocked after error", - 1797 : "Energy release today", - 1798 : "Grid creating generator", - 1799 : "No", - 1800 : "Generator", - 1801 : "Mains", - 1802 : "Mains and generator", - 1803 : "Invalid configuration for the PV generation counter", - 1804 : "Invalid configuration for the mains infeed counter", - 1805 : "Invalid configuration for the mains consumption counter", - 1806 : "Error in data transfer from the PV gen. counter", - 1807 : "Error in data transfer from mains infeed counter", - 1808 : "Error in data transfer from mains consump. counter", - 1809 : "Invalid configuration for the load control", - 1810 : "The communiction key has been replaced", - 1811 : "System time has been reset", - 1812 : "Serial number of the Bluetooth root node is |u0|-Zu4|", - 1813 : "Bluetooth connection quality to root node: |d0|%", - 1814 : "There is no Bluetooth conn.", - 1815 : "Establishing Bluetooth connection to root node", - 1816 : "Bluetooth connection failed", - 1817 : "Bluetooth connection to radio socket faulty. Load control not possible.", - 1818 : "Power outage", - 1819 : "Number of DC current measurement units", - 1820 : "USB connection 1", - 1821 : "External measurement of the insulation resistance", - 1822 : "Alignment not homogeneous", - 1823 : "PV connection not configured", - 1824 : "Arc detection triggered", - 1826 : "Encryption", - 1827 : "SSH", - 1828 : "Trigger time synchronisation", - 1829 : "Always SSL/TLS", - 1830 : "SSL/TLS if possible", - 1831 : "No encryption", - 1832 : "Connection to mains establ.", - 1833 : "Connection to mains disconn.", - 1834 : "Connection to mains collapsed", - 1835 : "Fault sensor module temp.", - 1836 : "Fan life-time reached", - 1837 : "Error in pyranometer", - 1838 : "Pyranometer calibr. necessary", - 1839 : "Backup mode switched on", - 1840 : "Communication to the Sunny Portal was disrupted for |s0| hours", - 1841 : "An error occurred in communication to the Sunny Portal: Error Code |d0|", - 1842 : "Transfer of the Firmware update Version number |u/9/0| for device type |tn4|. The transfer can take some time.", - 1843 : "Error when transferring the Firmware update Version number |u/9/0| for device type |tn4|. Procedure aborted.", - 1844 : "IGMP switched on", - 1845 : "Speedwire Group", - 1846 : "|tn4|: network busy", - 1847 : "|tn4|: network overloaded", - 1848 : "|tn4|: faulty data packages", - 1849 : "|tn4|: communication status goes to |tn8|", - 1850 : "|tn4|: communication disrupted", - 1851 : "|tn4|: connection speed goes to |tn8|", - 1852 : "|tn4|: duplex mode goes to |tn8|", - 1853 : "Load reduced through device reduction or increase of query interval", - 1854 : "Standalone operation", - 1855 : "Standalone operation", - 1856 : "Analogue current input 4", - 1857 : "Analogue voltage input 2", - 1858 : "Analogue voltage input 3", - 1859 : "Analogue voltage input 4", - 1860 : "Energy consumed internally", - 1861 : "|tn4|: Network load OK", - 1862 : "high", - 1863 : "Hardware recognition failed", - 1864 : "Unknown hardware ID", - 1865 : "Update transport started", - 1866 : "Update transport successful", - 1867 : "Update transport failed", - 1868 : "Communication with device currently not possible. Device may be switched off.", - 1869 : "Encrypt communication", - 1870 : "Communication monitoring signal", - 1871 : "Last successful upload", - 1872 : "every 30 minutes", - 1873 : "every 2 hours", - 1874 : "every 4 hours", - 1875 : "every 6 hours", - 1876 : "every 8 hours", - 1877 : "every 12 hours", - 1878 : "BT chip has been reinitialised", - 1879 : "Hardware ID", - 1880 : "Monitoring server", - 1881 : "Remove device", - 1882 : "Remove all devices", - 1883 : "Device", - 1887 : "System environment", - 1888 : "STP208HW12", - 1889 : "STP208HW13", - 1890 : "STP208HW14", - 1891 : "STP208HW15", - 1892 : "SMTP", - 1893 : "Active power", - 1894 : "Reactive power", - 1895 : "Digital inputs", - 1896 : "Analogue inputs", - 1897 : "Modbus", - 1898 : "Active power limits are being sent to plant", - 1899 : "Reactive power spec. is being sent to plant", - 1900 : "Invalid spec. for |tn0| from |tn4|", - 1901 : "New active power limits from |tn0| parameter |tn4| value |d8|%", - 1902 : "New reactive power spec. from |tn0| parameter |tn4| value |f8|%", - 1903 : "New reactive power spec. from |tn0| parameter |tn4| value |f8|", - 1904 : "New reactive power spec. from |tn0| parameter |tn4| value |tn8|", - 1905 : "Default status for |tn0| active", - 1906 : "Wind direction", - 1908 : "Reset communication data", - 1909 : "Delete system parameters in SPI", - 1910 : "Delete ODB experts in SPI", - 1911 : "Delete HP images in SPI", - 1912 : "Delete all firmware blocks in SPI", - 1913 : "Clear SPI flashes", - 1914 : "Reset CP", - 1915 : "Webconnect update", - 1916 : "Webconnect update failed", - 1917 : "PID quick stop triggered", - 1918 : "Self-test failed", - 1919 : "Insulation monitoring error", - 1920 : "Check insulation monitoring", - 1921 : "First error stack", - 1922 : "Stack error", - 1923 : "Cluster controller registration failed: |tn0|", - 1924 : "Cluster controller registered", - 1925 : "New devices registered", - 1926 : "Registration of new devices failed", - 1927 : "Heartbeat signal sending failed", - 1928 : "Network latency too high", - 1929 : "Test at maximum voltage", - 1930 : "Alarm at active power limit", - 1931 : "Alarm at reactive power specification", - 1932 : "Filter settings", - 1933 : "E-mail sent", - 1934 : "E-mail sending failed", - 1935 : "Alarm triggered. Event |d0| at device |d4|:|d8|", - 1936 : "Result of the last e-mail dispatch", - 1937 : "Set NetID: |s0|", - 1938 : "NetID 1 not supported", - 1939 : "|tn0| logs in from |ip4|", - 1940 : "Login from |ip0| failed", - 1941 : "|ip0| successfully logged off", - 1942 : "Parameter '%s' set successfully. |d4| to |d8|", - 1943 : "Parameter '%s' set successfully. |tn4| to |tn8|", - 1944 : "Parameter '%s' set successfully. Old value: |s4|", - 1945 : "Parameter '%s' set successfully. New value: |s4|", - 1946 : "Setting of parameter '%s' failed. |d4| to |d8|", - 1947 : "Setting of parameter '%s' failed. |tn4| to |tn8|", - 1948 : "Setting of parameter '%s' failed. Old value: |s4|", - 1949 : "Setting of parameter '%s' failed. New value: |s4|", - 1950 : "Watchdog reset |s0|", - 1951 : "Memory card detected (capacity|d0| MB, free |d4| MB)", - 1952 : "Memory card removed", - 1953 : "Memory card nearly full (capacity|d0| MB, free |d4| MB)", - 1954 : "Memory card write-protected", - 1955 : "Memory card not detected or not readable", - 1956 : "Memory card full (capacity|d0| MB, free |d4| MB)", - 1957 : "Memory card full", - 1958 : "No memory card inserted", - 1959 : "Syslog service act. until: |ts0|", - 1960 : "Error occurred in the FTP Push conn. test: |tn0|", - 1961 : "Target computer does not respond", - 1962 : "Connection rejected by target computer", - 1963 : "Too many users logged in", - 1964 : "Incorrect user name or password", - 1965 : "File/directory not found or no access rights", - 1966 : "An error occurred during FTP upload: |tn0|", - 1967 : "Energy values for device |u0|:|u4| for time from |ts8| to |tsc| resent", - 1968 : "Active power limitation: |b0|%/|b1|%/|b2|% (|x9|-|x8|-|x7|-|x6|-|x5|-|x4|)", - 1969 : "Reactive power spec.: |b0|%/|b1|%/|b2|% (|x9|-|x8|-|x7|-|x6|-|x5|-|x4|)", - 1970 : "cosPhi spec.: |f0| (|x9|-|x8|-|x7|-|x6|-|x5|-|x4|)", - 1971 : "Unknown PRB attempted to change |tn0|", - 1972 : "Communication error: Contact to device |tn0|, SN: |u4| overdue (last contact: |ts8|)", - 1973 : "X-axes reference", - 1974 : "Y-axes reference", - 1975 : "Voltage in V", - 1976 : "Voltage in percentages of Un", - 1977 : "Var in percentages of Pmax", - 1978 : "Power in percentages of Pmax", - 1979 : "Power in percentages of frozen active power", - 1980 : "X value 7", - 1981 : "Y value 7", - 1982 : "X value 8", - 1983 : "Y value 8", - 1984 : "Reactive power/volt. char. Q(U) with meas. points", - 1985 : "Conf. of reactive power/volt. char. Q(U) with meas. points", - 1986 : "Activating active power", - 1987 : "Deactivating active power", - 1988 : "Min. time until activation of active power gradient after reset frequency", - 1989 : "Activating voltage", - 1990 : "Deactivating voltage", - 1991 : "Characteristic 2", - 1992 : "Plant switches to status |tn0|", - 1993 : "directly after 'Upload'", - 1994 : "Active power currently limited due to AC current limitation", - 1995 : "EPS relay fails to open or close", - 1996 : "Modbus |tn0| started", - 1997 : "Modbus |tn0| terminated", - 1998 : "An error occurred during startup of Modbus |tn0|: port |d4|", - 1999 : "Modbus configurations file |s0| successfully loaded", - 2000 : "Modbus configurations file |s0| corrupt", - 2001 : "SMACOM C", - 2002 : "SMACOM D", - 2003 : "Power control module", - 2004 : "Status of digital inputs", - 2005 : "Remote shut-down", - 2006 : "Input C defective", - 2007 : "Fault in wind sensor", - 2008 : "Lower frequ. deviation limit prior to active power release", - 2009 : "Upper frequ. dev. limit prior to active power release", - 2010 : "Application-ID", - 2011 : "Switchable maximum threshold", - 2012 : "Switchable maximum threshold tripping time", - 2013 : "Switchable minimum threshold", - 2014 : "Switchable minimum threshold tripping time", - 2015 : "Operating mode of frequency restriction", - 2016 : "Source of quick shut-down", - 2017 : "Frequency band narrowing", - 2018 : "IEC 61850 configuration", - 2019 : "GOOSE configuration", - 2020 : "61850 GOOSE", - 2021 : "Alarm upon warnings", - 2022 : "Alternative e-mail sender address (optional)", - 2023 : "Absolute", - 2024 : "In percentages", - 2025 : "File upload successful: |s0|", - 2026 : "File upload failed: |s0|", - 2027 : "File upload rejected: |s0|", - 2028 : "NSS quick stop: |tn0| through |tn4| is executed", - 2029 : "Webconnect enabled", - 2030 : "Webconnect disabled", - 2031 : "Webconnect error: no connection", - 2032 : "Default gateway not configured", - 2033 : "DNS server not configured", - 2034 : "No reply to DNS request", - 2035 : "SIP proxy DNS resolution failed", - 2036 : "Stun server DNS resolution failed", - 2037 : "No reply to request to Stun server", - 2038 : "No reply to SIP option packs", - 2039 : "Registration rejected by SIP registrar", - 2040 : "Storage medium detected at USB2; USB1 not assigned, thus no logging", - 2042 : "Power per phase", - 2043 : "Reactive power setpoint Q", - 2044 : "Change excitation type", - 2045 : "Do not change excitation type", - 2046 : "Internal SD card defective", - 2047 : "Data retention refresh started", - 2048 : "Data retention refresh completed", - 2049 : "NSS not forwarded, is deactivated", - 2050 : "Invalid NSS command", - 2051 : "Invalid RPC command", - 2052 : "E-mail could not be sent. SMTP error code: |d0|", - 2053 : "Digital input group 1 (DI1 .. DI4)", - 2054 : "Digital input group 2 (DI5 .. DI8)", - 2055 : "DI1", - 2056 : "DI1 DI2", - 2057 : "DI1 DI2 DI3", - 2058 : "DI1 DI2 DI3 DI4", - 2059 : "DI1 DI2 DI4", - 2060 : "DI1 DI3", - 2061 : "DI1 DI3 DI4", - 2062 : "DI1 DI4", - 2063 : "DI2", - 2064 : "DI2 DI3", - 2065 : "DI2 DI3 DI4", - 2066 : "DI2 DI4", - 2067 : "DI3", - 2068 : "DI3 DI4", - 2069 : "DI4", - 2070 : "DI5", - 2071 : "DI5 DI6", - 2072 : "DI5 DI6 DI7", - 2073 : "DI5 DI6 DI7 DI8", - 2074 : "DI5 DI6 DI8", - 2075 : "DI5 DI7", - 2076 : "DI5 DI7 DI8", - 2077 : "DI5 DI8", - 2078 : "DI6", - 2079 : "DI6 DI7", - 2080 : "DI6 DI7 DI8", - 2081 : "DI6 DI8", - 2082 : "DI7", - 2083 : "DI7 DI8", - 2084 : "DI8", - 2085 : "Unknown SIP registry", - 2086 : "Webconnect error: Default gateway not configured", - 2087 : "Webconnect error: DNS server not configured", - 2088 : "Webconnect error: No reply to DNS request |s0|", - 2089 : "Webconnect error: Unknown SIP proxy |s0|", - 2090 : "Webconnect error: Unknown STUN server", - 2091 : "Webconnect error: No reply to request to STUN server", - 2092 : "Webconnect error: No reply to SIP option packs", - 2093 : "Webconnect error: Registration rejected by SIP registrar", - 2094 : "Webconnect error: Unknown SIP registrar |s0|", - 2095 : "Webconnect error: Faulty communication", - 2096 : "STP208HW11", - 2097 : "Phase L2 gegen L3", - 2098 : "Phase L3 against L1", - 2099 : "Power unit supplies data", - 2100 : "Power limitation to prevent load unbalance", - 2101 : "Insulation measurement", - 2102 : "Frequency restr. due to timeout in |tn0|", - 2103 : "Inconsistent communication version", - 2104 : "Invalid device combination", - 2105 : "Max. permitted number of inverters exceeded", - 2106 : "Generator voltage too high", - 2107 : "Mirror new complete pack", - 2108 : "Remove inverter or delete removed inverters", - 2110 : "Unsupported data system to |s0|", - 2111 : "Voltage increase protection trigger time", - 2112 : "Goose-Mac address", - 2113 : "Grid connection point", - 2114 : "Active power specification", - 2115 : "Reactive power specification", - 2116 : "Active power limitation", - 2117 : "Generator control", - 2118 : "Configuration of generator control", - 2119 : "Derating", - 2120 : "RCD adjustment", - 2121 : "30 mA", - 2122 : "40 mA", - 2123 : "50 mA", - 2124 : "60 mA", - 2125 : "70 mA", - 2126 : "80 mA", - 2127 : "90 mA", - 2128 : "100 mA", - 2130 : "Connection establishment", - 2131 : "Data transfer from PV generation counter OK", - 2132 : "Data transfer from mains infeed counter OK", - 2133 : "Data transfer from mains consumption counter OK", - 2134 : "Nominal power", - 2135 : "Operating mode of active power limitation", - 2136 : "Dynamic active power limitation", - 2137 : "Fixed specification in Watt", - 2138 : "Fixed specification in percentages", - 2139 : "Characteristic curve", - 2140 : "Set active power limit", - 2141 : "Configuration of network switch failed", - 2142 : "Configuration of network switch successful", - 2143 : "Relay defect confirmed", - 2144 : "Dynamic active power limitation started.", - 2145 : "Dynamic active power limitation terminated.", - 2146 : "Act. power limitation deactivated due to incorr. configuration.", - 2147 : "Supplied power: |u0| W (permitted value: |u4| W)", - 2148 : "Active power was limited today for |u0| minutes.", - 2149 : "Fault: act. power limitation activated w/o regard to own consumption", - 2150 : "Own consumption again included for active power limitation.", - 2151 : "Permanent 0 W grid supply measured No active power limitation possible, if meter is faulty", - 2152 : "Inverter fails to respond to act. power limitation.", - 2153 : "Self-test started manually", - 2154 : "Manually started self-start completed successfully", - 2155 : "Supplied power has exceeded the permitted value several times.", - 2156 : "Registration of the SIP registry has not responded", - 2157 : "Webconnect error: registration of the SIP registry has not responded", - 2158 : "Permanent freq. restriction", - 2159 : "Condition test successful", - 2160 : "Condition test failed", - 2161 : "STP267HW07", - 2162 : "Number of section switches", - 2163 : "Time to open", - 2164 : "Time to close", - 2165 : "Section switches", - 2166 : "DC overvoltage because of power limit", - 2167 : "Max. operating cycles of the GFDI reached", - 2168 : "Replace GFDI", - 2169 : "React. power spec.: |d0|%/|d4|%/|d8|%", - 2170 : "cos Phi spec.: |f0|/|f4|/|f8| |tnc|", - 2171 : "Discharge cut-off voltage", - 2172 : "Maximum charge current", - 2173 : "Maximum discharge current", - 2174 : "Cell charge nominal voltage for boost charge", - 2175 : "Cell charge nominal voltage for full charging", - 2176 : "Cell charge nominal voltage for equalisation", - 2177 : "Cell charge nominal voltage for trickle charge", - 2178 : "Hysteresis minimum threshold", - 2179 : "Hysteresis maximum threshold", - 2180 : "Maximum reverse power", - 2181 : "Maximum reverse power tripping time", - 2182 : "Measurements of external power connection", - 2183 : "Mains oper. without feed back", - 2184 : "Energy saving in the network", - 2185 : "End energy saving in the network", - 2186 : "Start energy saving in the network", - 2187 : "|tn0| logs on", - 2188 : "Access to |x0||x1|:|x2||x3|:|x4||x5|:|x6||x7|:|x8||x9|:|xa||xb|:|xc||xd|:|xe||xf|", - 2189 : "Logging on |x0||x1|:|x2||x3|:|x4||x5|:|x6||x7|:|x8||x9|:|xa||xb|:|xc||xd|:|xe||xf| failed", - 2190 : "|x0||x1|:|x2||x3|:|x4||x5|:|x6||x7|:|x8||x9|:|xa||xb|:|xc||xd|:|xe||xf| was successfully logged off", - 2191 : "Minimum operating temperature not reached", - 2192 : "Update Zigbee", - 2193 : "Zigbee update failed", - 2194 : "Energy transfer not possible", - 2195 : "Number of UCP events", - 2196 : "Derating because of low DC voltage", - 2197 : "Derating because of power and DC voltage", - 2198 : "Bias voltage", - 2199 : "Relative", - 2200 : "Nominal apparent voltage", - 2201 : "Low-voltage powerline", - 2202 : "Medium-voltage powerline", - 2203 : "Transformer", - 2204 : "Ohmic resistive coating", - 2205 : "Inductive reactive coating", - 2206 : "Capacitive reactive coating", - 2207 : "Short-circuit voltage", - 2208 : "Nominal voltage of the high-voltage side", - 2210 : "Length of the low-voltage powerline", - 2211 : "Length of the medium-voltage powerline", - 2212 : "AC voltage measurement on the inverter side less than a mains voltage measurement", - 2213 : "AC voltage measurement on the mains side less than inverter side voltage measurement", - 2214 : "AC voltage measurement of the mains limit controller is defective", - 2215 : "AC elect. measurem. is defect.", - 2216 : "AC voltage measurement shows a whine on mains side", - 2217 : "Defective precharging circuit", - 2218 : "Check AC meas. cable and AC voltage sensing", - 2221 : "Check AC cable and AC power meas.", - 2222 : "Check parameter settings of the DSP", - 2223 : "Check precharg. circuit and fuses", - 2224 : "Precharging circuit active", - 2225 : "Pure reactive power operation, QonDemand active", - 2226 : "Reverse current detection (immed. separation from the PV field)", - 2227 : "General firmware error: |u0|", - 2228 : "General firmware warning: |u0|", - 2229 : "General error: |u0|/|u4|/|u8|/|uc|", - 2230 : "Capacitor self-test failed", - 2231 : "Check capacitor", - 2232 : "SMA energy meter purchase", - 2233 : "SMA energy meter supply", - 2234 : "PIC", - 2235 : "SMA energy meter purchase and supply", - 2236 : "PLC communication impaired", - 2237 : "PLC communication impaired", - 2238 : "Power line communication", - 2239 : "Package error rate", - 2240 : "Intermediate circuit voltages not permitted (SW)", - 2241 : "Wrong config: simultan. communication via bluetooth and speedwire", - 2242 : "Overvoltage suppression P (U)", - 2243 : "Overvoltage suppression Q (U)", - 2244 : "Serial Number", - 2245 : "Active power limitation", - 2246 : "D1: 0 | D2: 0 | D3: 0 | D4: 0", - 2247 : "D1: 1 | D2: 0 | D3: 0 | D4: 0", - 2248 : "D1: 0 | D2: 1 | D3: 0 | D4: 0", - 2249 : "D1: 1 | D2: 1 | D3: 0 | D4: 0", - 2250 : "D1: 0 | D2: 0 | D3: 1 | D4: 0", - 2251 : "D1: 1 | D2: 0 | D3: 1 | D4: 0", - 2252 : "D1: 0 | D2: 1 | D3: 1 | D4: 0", - 2253 : "D1: 1 | D2: 1 | D3: 1 | D4: 0", - 2254 : "D1: 0 | D2: 0 | D3: 0 | D4: 1", - 2255 : "D1: 1 | D2: 0 | D3: 0 | D4: 1", - 2256 : "D1: 0 | D2: 1 | D3: 0 | D4: 1", - 2257 : "D1: 1 | D2: 1 | D3: 0 | D4: 1", - 2258 : "D1: 0 | D2: 0 | D3: 1 | D4: 1", - 2259 : "D1: 1 | D2: 0 | D3: 1 | D4: 1", - 2260 : "D1: 0 | D2: 1 | D3: 1 | D4: 1", - 2261 : "D1: 1 | D2: 1 | D3: 1 | D4: 1", - 2262 : "Release time", - 2263 : "Release value", - 2264 : "Error tolerance time", - 2265 : "Oper. mode of the stat.volt.maint. for Q on demand", - 2266 : "Conf. of the static voltage maint. at Q on demand", - 2267 : "Gradient K of react. current stat. for undervolt.", - 2268 : "Gradient K of reactive current stat. for overvolt.", - 2269 : "Reactive power charact. curve", - 2270 : "cos Phi or Q specification through optimum plant control", - 2271 : "Active power as a percentage of Pmax", - 2272 : "cos Phi (EEI convention)", - 2273 : "Conf. of the reactive power characteristic curve", - 2274 : "Activation of the characteristic curve", - 2275 : "Activation threshold", - 2276 : "Deactivation threshold", - 2277 : "Threshold reference", - 2278 : "Supporting points of the characteristic curve 1", - 2279 : "Supporting points of the characteristic curve 2", - 2280 : "Supporting points of the characteristic curve 3", - 2281 : "X value", - 2282 : "Y value", - 7500 : "Enel-GUIDA", - 7501 : "RD1663/661-A", - 7502 : "IEC61727/MEA", - 7503 : "IEC61727/PEA", - 7504 : "SI4777-2", - 7505 : "CGC/GF001", - 7506 : "VDE0126-1-1/UTE", - 7507 : "KEMCO502/2009", - 7510 : "VDE-AR-N4105", - 7511 : "GB-T19939-2005", - 7512 : "G59/2", - 7513 : "VDE-AR-N4105-MP", - 7514 : "VDE-AR-N4105-HP", - 7515 : "KEMCO501/2009", - 7516 : "CEI 0-21", - 7517 : "CEI 0-21 internal", - 7518 : "CEI 0-21 external", - 7519 : "UL1741/2010/277", - 7520 : "UL1741/2010/120", - 7521 : "UL1741/2010/240", - 7522 : "NEN-EN50438", - 7523 : "C10/11/2012", - 7524 : "RD1699", - 8000 : "All Devices", - 8001 : "Solar Inverter", - 8002 : "Wind Turbine Inverter", - 8007 : "Battery Inverter", - 8033 : "Consumer", - 8064 : "Sensor System in General", - 8065 : "Electricity meter", - 8128 : "Communication products", - 8500 : "ROOT", - 8501 : "VMEM", - 8502 : "PWT", - 8503 : "COM", - 8504 : "FWCHK", - 8505 : "COND", - 8506 : "SET", - 8507 : "LOGDEV", - 8508 : "LOGOBJ", - 8509 : "TAGS", - 8510 : "PHYDEV", - 8511 : "PHYOBJ", - 8512 : "LEXE", - 8513 : "LEXN", - 8514 : "LEXA", - 8515 : "LS", - 8530 : "Counter object", - 8531 : "5-min value object", - 8532 : "Instantaneous value object", - 8533 : "Status object", - 8534 : "Parameter object", - 8535 : "PV string group mean values", - 8536 : "String list object", - 8537 : "PV string group parameter", - 8538 : "PV string group instantaneous values", - 8539 : "Adaptor information", - 8540 : "Data logger object energy", - 8541 : "Data logger object event", - 8542 : "Data logger object daily energy", - 8543 : "Event counter object", - 8544 : "Event object", - 8545 : "Taglist object", - 8546 : "Time setting object", - 8547 : "Plant control parameter", - 8548 : "PV voltage level mean values", - 8549 : "PV voltage level instantaneous values", - 8550 : "PV voltage level parameter", - 8551 : "Plant control object", - 8552 : "PV voltage level status", - 8553 : "Data logger object supplied power", - 8554 : "Data logger object consumed power", - 8555 : "Data logger object supplied daily power", - 8556 : "Data logger object consumed daily power", - 8557 : "External plant control object", - 9000 : "SWR 700", - 9001 : "SWR 850", - 9002 : "SWR 850E", - 9003 : "SWR 1100", - 9004 : "SWR 1100E", - 9005 : "SWR 1100LV", - 9006 : "SWR 1500", - 9007 : "SWR 1600", - 9008 : "SWR 1700E", - 9009 : "SWR 1800U", - 9010 : "SWR 2000", - 9011 : "SWR 2400", - 9012 : "SWR 2500", - 9013 : "SWR 2500U", - 9014 : "SWR 3000", - 9015 : "SB 700", - 9016 : "SB 700U", - 9017 : "SB 1100", - 9018 : "SB 1100U", - 9019 : "SB 1100LV", - 9020 : "SB 1700", - 9021 : "SB 1900TLJ", - 9022 : "SB 2100TL", - 9023 : "SB 2500", - 9024 : "SB 2800", - 9025 : "SB 2800i", - 9026 : "SB 3000", - 9027 : "SB 3000US", - 9028 : "SB 3300", - 9029 : "SB 3300U", - 9030 : "SB 3300TL", - 9031 : "SB 3300TL HC", - 9032 : "SB 3800", - 9033 : "SB 3800U", - 9034 : "SB 4000US", - 9035 : "SB 4200TL", - 9036 : "SB 4200TL HC", - 9037 : "SB 5000TL", - 9038 : "SB 5000TLW", - 9039 : "SB 5000TL HC", - 9040 : "Convert 2700", - 9041 : "SMC 4600A", - 9042 : "SMC 5000", - 9043 : "SMC 5000A", - 9044 : "SB 5000US", - 9045 : "SMC 6000", - 9046 : "SMC 6000A", - 9047 : "SB 6000US", - 9048 : "SMC 6000UL", - 9049 : "SMC 6000TL", - 9050 : "SMC 6500A", - 9051 : "SMC 7000A", - 9052 : "SMC 7000HV", - 9053 : "SB 7000US", - 9054 : "SMC 7000TL", - 9055 : "SMC 8000TL", - 9056 : "SMC 9000TL-10", - 9057 : "SMC 10000TL-10", - 9058 : "SMC 11000TL-10", - 9059 : "SB 3000 K", - 9060 : "Unknown device", - 9061 : "SensorBox", - 9062 : "SMC 11000TLRP", - 9063 : "SMC 10000TLRP", - 9064 : "SMC 9000TLRP", - 9065 : "SMC 7000HVRP", - 9066 : "SB 1200", - 9067 : "STP 10000TL-10", - 9068 : "STP 12000TL-10", - 9069 : "STP 15000TL-10", - 9070 : "STP 17000TL-10", - 9071 : "SB 2000HF-30", - 9072 : "SB 2500HF-30", - 9073 : "SB 3000HF-30", - 9074 : "SB 3000TL-21", - 9075 : "SB 4000TL-21", - 9076 : "SB 5000TL-21", - 9077 : "SB 2000HFUS-30", - 9078 : "SB 2500HFUS-30", - 9079 : "SB 3000HFUS-30", - 9080 : "SB 8000TLUS", - 9081 : "SB 9000TLUS", - 9082 : "SB 10000TLUS", - 9083 : "SB 8000US", - 9084 : "WB 3600TL-20", - 9085 : "WB 5000TL-20", - 9086 : "SB 3800US-10", - 9087 : "Sunny Beam BT11", - 9088 : "Sunny Central 500CP", - 9089 : "Sunny Central 630CP", - 9090 : "Sunny Central 800CP", - 9091 : "Sunny Central 250U", - 9092 : "Sunny Central 500U", - 9093 : "Sunny Central 500HEUS", - 9094 : "Sunny Central 760CP", - 9095 : "Sunny Central 720CP", - 9096 : "Sunny Central 910CP", - 9097 : "SMU8", - 9098 : "STP 5000TL-20", - 9099 : "STP 6000TL-20", - 9100 : "STP 7000TL-20", - 9101 : "STP 8000TL-10", - 9102 : "STP 9000TL-20", - 9103 : "STP 8000TL-20", - 9104 : "SB 3000TL-JP-21", - 9105 : "SB 3500TL-JP-21", - 9106 : "SB 4000TL-JP-21", - 9107 : "SB 4500TL-JP-21", - 9108 : "SCSMC", - 9109 : "SB 1600TL-10", - 9110 : "SSM US", - 9111 : "SMA radio-controlled socket", - 9112 : "WB 2000HF-30", - 9113 : "WB 2500HF-30", - 9114 : "WB 3000HF-30", - 9115 : "WB 2000HFUS-30", - 9116 : "WB 2500HFUS-30", - 9117 : "WB 3000HFUS-30", - 9118 : "VIEW-10", - 9119 : "Sunny Home Manager", - 9120 : "SMID", - 9121 : "Sunny Central 800HE-20", - 9122 : "Sunny Central 630HE-20", - 9123 : "Sunny Central 500HE-20", - 9124 : "Sunny Central 720HE-20", - 9125 : "Sunny Central 760HE-20", - 9126 : "SMC 6000A-11", - 9127 : "SMC 5000A-11", - 9128 : "SMC 4600A-11", - 9129 : "SB 3800-11", - 9130 : "SB 3300-11", - 9131 : "STP 20000TL-10", - 9132 : "SMA CT Meter", - 9133 : "SB 2000HFUS-32", - 9134 : "SB 2500HFUS-32", - 9135 : "SB 3000HFUS-32", - 9136 : "WB 2000HFUS-32", - 9137 : "WB 2500HFUS-32", - 9138 : "WB 3000HFUS-32", - 9139 : "STP 20000TLHE-10", - 9140 : "STP 15000TLHE-10", - 9141 : "SB 3000US-12", - 9142 : "SB 3800US-12", - 9143 : "SB 4000US-12", - 9144 : "SB 5000US-12", - 9145 : "SB 6000US-12", - 9146 : "SB 7000US-12", - 9147 : "SB 8000US-12", - 9148 : "SB 8000TLUS-12", - 9149 : "SB 9000TLUS-12", - 9150 : "SB 10000TLUS-12", - 9151 : "SB 11000TLUS-12", - 9152 : "SB 7000TLUS-12", - 9153 : "SB 6000TLUS-12", - 9154 : "SB 1300TL-10", - 9155 : "Sunny Backup 2200", - 9156 : "Sunny Backup 5000", - 9157 : "Sunny Island 2012", - 9158 : "Sunny Island 2224", - 9159 : "Sunny Island 5048", - 9160 : "SB 3600TL-20", - 9161 : "SB 3000TL-JP-22", - 9162 : "SB 3500TL-JP-22", - 9163 : "SB 4000TL-JP-22", - 9164 : "SB 4500TL-JP-22", - 9165 : "SB 3600TL-21", - 9167 : "Cluster Controller", - 9168 : "SC630HE-11", - 9169 : "SC500HE-11", - 9170 : "SC400HE-11", - 9171 : "WB 3000TL-21", - 9172 : "WB 3600TL-21", - 9173 : "WB 4000TL-21", - 9174 : "WB 5000TL-21", - 9175 : "SC 250", - 9176 : "SMA Meteo Station", - 9177 : "SB 240-10", - 9178 : "SB 240-US-10", - 9179 : "Multigate-10", - 9180 : "Multigate-US-10", - 9181 : "STP 20000TLEE-10", - 9182 : "STP 15000TLEE-10", - 9183 : "SB 2000TLST-21", - 9184 : "SB 2500TLST-21", - 9185 : "SB 3000TLST-21", - 9186 : "WB 2000TLST-21", - 9187 : "WB 2500TLST-21", - 9188 : "WB 3000TLST-21", - 9189 : "WTP 5000TL-20", - 9190 : "WTP 6000TL-20", - 9191 : "WTP 7000TL-20", - 9192 : "WTP 8000TL-20", - 9193 : "WTP 9000TL-20", - 9194 : "STP 12000TL-US-10", - 9195 : "STP 15000TL-US-10", - 9196 : "STP 20000TL-US-10", - 9197 : "STP 24000TL-US-10", - 9198 : "SB 3000TLUS-22", - 9199 : "SB 3800TLUS-22", - 9200 : "SB 4000TLUS-22", - 9201 : "SB 5000TLUS-22", - 9202 : "WB 3000TLUS-22", - 9203 : "WB 3800TLUS-22", - 9204 : "WB 4000TLUS-22", - 9205 : "WB 5000TLUS-22", - 9206 : "SC 500CP-JP", - 9207 : "SC 850CP", - 9208 : "SC 900CP", - 9209 : "SC 850HE-20", - 9210 : "SC 900HE-20", - 9211 : "SC 619CP", - 9212 : "SMA Meteo Station", - 9213 : "SC 800 CP-US", - 9214 : "SC 630 CP-US", - 9215 : "SC 500 CP-US", - 9216 : "SC 720 CP-US", - 9217 : "SC 750 CP-US", - 9218 : "SB 240 Dev", - 9219 : "SB 240-US BTF", - 9220 : "Grid Gate-20", - 9221 : "SC 500 CP-US/600V", - 9222 : "STP 10000TLEE-JP-10", - 9223 : "Sunny Island 6.0H", - 9224 : "Sunny Island 8.0H", - 9225 : "SB 5000SE-10", - 9226 : "SB 3600SE-10", - 9227 : "", - 9228 : "", - 9500 : "(UTC+04:30) Kabul", - 9501 : "(UTC-09:00) Alaska", - 9502 : "(UTC+03:00) Kuwait, Riyardh", - 9503 : "(UTC+04:00) Abu Dhabi, Muskat", - 9504 : "(UTC+03:00) Baghdad", - 9505 : "(UTC-04:00) Atlantic (Canada)", - 9506 : "(UTC+09:30) Darwin", - 9507 : "(UTC+10:00) Canberra, Melbourne, Sydney", - 9508 : "(UTC+04:00) Baku", - 9509 : "(UTC-01:00) Azores", - 9510 : "(UTC-06:00) Saskatchewan", - 9511 : "(UTC-01:00) Cape Verde Islands", - 9512 : "(UTC+04:00) Yerevan", - 9513 : "(UTC+09:30) Adelaide", - 9515 : "(UTC+06:00) Astana, Dhaka", - 9516 : "(UTC-04:00) Manaus", - 9517 : "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", - 9518 : "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", - 9519 : "(UTC+11:00) Magadan, Solomon Islands, New Caledonia", - 9520 : "(UTC-06:00) Central America", - 9521 : "(UTC-06:00) Guadalajara, Mexico City, Monterrary - Old", - 9522 : "(UTC+08:00) Peking, Chongqing, Hongkong, Urumchi", - 9523 : "(UTC-12:00) (Western) International Date Line", - 9524 : "(UTC+03:00) Nairobi", - 9525 : "(UTC+10:00) Brisbane", - 9526 : "(UTC+02:00) Minsk", - 9527 : "(UTC-03:00) Brasilia", - 9528 : "(UTC-05:00) New York, Miami, Atlanta, Detroit, Toronto", - 9529 : "(UTC+02:00) Cairo", - 9530 : "(UTC+05:00) Jekaterinburg", - 9531 : "(UTC+12:00) Fidschi, Marshall Islands", - 9532 : "(UTC+02:00) Helsinki, Kiev, Riga, Sofia, Tallin, Wilna", - 9533 : "(UTC+04:00) Tiflis", - 9534 : "(UTC) Dublin, Edinburgh, Lisbon, London", - 9535 : "(UTC-03:00) Greenland", - 9536 : "(UTC) Monrovia, Reykjavik", - 9537 : "(UTC+02:00) Athens, Bucharest, Istanbul", - 9538 : "(UTC-10:00) Hawaii", - 9539 : "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", - 9540 : "(UTC+03:30) Teheran", - 9541 : "(UTC+02:00) Jerusalem", - 9542 : "(UTC+02:00) Amman", - 9543 : "(UTC+09:00) Seoul", - 9544 : "(UTC+08:00) Kuala Lumpur, Singapore", - 9545 : "(UTC-02:00) Central Atlantic", - 9546 : "(UTC+02:00) Beirut", - 9547 : "(UTC-07:00) Denver, Salt Lake City, Calgary", - 9548 : "(UTC-07:00) Chihuahua, La Paz, Mazatlan - old", - 9549 : "(UTC+06:30) Yangon (Rangoon)", - 9550 : "(UTC+06:00) Novosibirsk", - 9551 : "(UTC+02:00) Windhoek", - 9552 : "(UTC+05:45) Katmandu", - 9553 : "(UTC+12:00) Auckland, Wellington", - 9554 : "(UTC-03:30) Newfoundland", - 9555 : "(UTC+08:00) Irkutsk", - 9556 : "(UTC+07:00) Krasnoyarsk", - 9557 : "(UTC-04:00) Santiago", - 9558 : "(UTC-08:00) Pacific (USA, Canada)", - 9559 : "(UTC-08:00) Tijuana, Baja California (Mexico)", - 9560 : "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", - 9561 : "(UTC+03:00) Moskow, St. Petersburg, Volgograd", - 9562 : "(UTC-03:00) Buenos Aires", - 9563 : "(UTC-05:00) Bogota, Lima, Quito", - 9564 : "(UTC-04:30) Caracas", - 9565 : "(UTC-11:00) Midway Islands, Samoa", - 9566 : "(UTC+07:00) Bangkok, Hanoi, Jakarta", - 9567 : "(UTC+02:00) Harare, Pretoria", - 9568 : "(UTC+05:30) Sri Jayawardenepura", - 9569 : "(UTC+08:00) Taipeh", - 9570 : "(UTC+10:00) Hobart", - 9571 : "(UTC+09:00) Osaka, Sapporo, Tokyo", - 9572 : "(UTC+13:00) Nuku'alofa", - 9573 : "(UTC-05:00) Indiana (East)", - 9574 : "(UTC-07:00) Arizona", - 9575 : "(UTC+10:00) Vladisvostok", - 9576 : "(UTC+08:00) Perth", - 9577 : "(UTC+01:00) West.Centr.Africa", - 9578 : "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", - 9579 : "(UTC+05:00) Islamabad, Karatschi", - 9580 : "(UTC+10:00) Guam, Port Moresby", - 9581 : "(UTC+09:00) Yakutsk", - 9582 : "(UTC+04:00) Caucasian Standard Time", - 9583 : "(UTC-06:00) Chicago, Dallas, Kansas City, Winnipeg", - 9584 : "(UTC-06:00) Guadalajara, Mexico City, Monterrey - new", - 9585 : "(UTC) Casablanca", - 9586 : "(UTC+04:00) Port Louis", - 9587 : "(UTC-07:00) Chihuahua, La Paz, Mazatlan - new", - 9588 : "(UTC-03:00) Montevideo", - 9589 : "(UTC+05:00) Taschkent", - 9591 : "(UTC-04:00) Georgetown, La Paz, San Juan", - 9592 : "(UTC+08:00) Ulan-Bator", - 9593 : "(UTC-03:00) Cayenne", - 9594 : "(UTC-04:00) Asuncion", - 9595 : "(UTC+12:00) Petropavlovsk-Kamtschatski", - 10001 : "Total yield", - 10005 : "Absorbed energy", - 10009 : "Number of events for user", - 10010 : "Number of grid connections", - 10011 : "Operating time", - 10012 : "Feed-in time", - 10013 : "Number of events for installer", - 10014 : "Number of events for service", - 10015 : "Total energy absorbed from the grid by the device", - 10016 : "Total amount of energy fed into the grid by device", - 10017 : "Total operating time of device", - 10018 : "Total feed-in time of device", - 10019 : "Number of grid connections of the device", - 10020 : "Fan operating time", - 10021 : "Fan 2 operating time", - 10022 : "Fan heat sink operating time", - 10023 : "Fan transformer operating time", - 10024 : "Fan transformer 2 operating time", - 10025 : "Number of Flash write cycles", - 10026 : "Number of events for developer", - 10027 : "Current event number", - 10028 : "Waiting time until feed-in", - 10030 : "Power", - 10031 : "Power L1", - 10032 : "Power L2", - 10033 : "Power L3", - 10035 : "Grid voltage phase L1", - 10036 : "Grid voltage phase L2", - 10037 : "Grid voltage phase L3", - 10038 : "Grid current", - 10039 : "Grid current phase L1", - 10040 : "Grid current phase L2", - 10041 : "Grid current phase L3", - 10042 : "Grid frequency", - 10043 : "Reactive power", - 10044 : "Reactive power L1", - 10045 : "Reactive power L2", - 10046 : "Reactive power L3", - 10047 : "Apparent power", - 10048 : "Apparent power L1", - 10049 : "Apparent power L2", - 10050 : "Apparent power L3", - 10051 : "Operating condition residual current", - 10052 : "Operating condition insulation resistance", - 10053 : "Operating condition grid voltage", - 10054 : "Operating condition grid voltage L1", - 10055 : "Operating condition grid voltage L2", - 10056 : "Operating condition grid voltage L3", - 10057 : "Operating condition grid frequency", - 10058 : "Operating condition power", - 10061 : "Operating condition reactive power", - 10063 : "Operating condition current", - 10064 : "Operating condition current L1", - 10065 : "Operating condition current L2", - 10066 : "Operating condition current L3", - 10067 : "Operating condition temperatures", - 10068 : "Highest measured ambient temperature", - 10069 : "Ambient temperature", - 10070 : "Insolation", - 10071 : "Diffuse insolation", - 10072 : "Direct irradiation", - 10073 : "Insolation on external sensor", - 10074 : "Wind speed", - 10075 : "Wind direction", - 10076 : "Air humidity", - 10077 : "Atmospheric pressure", - 10078 : "Residual current", - 10079 : "Insulation resistance", - 10080 : "Serial number", - 10081 : "Nominal power in Ok Mode", - 10082 : "Nominal power in Warning Mode", - 10083 : "Nominal power in Fault Mode", - 10085 : "Recommended action 'contact installer'", - 10086 : "Recommended action 'contact manufacturer'", - 10087 : "External temperature", - 10088 : "Highest measured external temperature", - 10089 : "External temperature 2", - 10090 : "Highest measured external temperature 2", - 10091 : "Internal temperature", - 10092 : "Highest measured internal temperature", - 10093 : "Heat sink temperature", - 10094 : "Highest measured heat sink temperature", - 10095 : "Heat sink temperature 2", - 10096 : "Highest measured heat sink temperature 2", - 10097 : "Transformer temperature", - 10098 : "Highest measured transformer temperature", - 10101 : "Module temperature", - 10102 : "Highest measured module temperature", - 10103 : "Highest measured inverter temperature", - 10104 : "Inverter temperature", - 10105 : "Highest measured printed circuit board temperature", - 10106 : "Printed circuit board temperature", - 10107 : "Last GridGuard password", - 10108 : "Intermediate circuit voltage", - 10109 : "Current event number for manufacturer", - 10110 : "Condition", - 10111 : "Recommended action", - 10112 : "Message", - 10113 : "Fault correction measure", - 10114 : "Grid relay/contactor", - 10115 : "Derating", - 10116 : "DC voltage control type", - 10119 : "Acknowledge fault", - 10120 : "Remote control", - 10121 : "Maximum active power device", - 10122 : "Memory card status", - 10123 : "Operating condition", - 10124 : "Fan test", - 10125 : "Deactivation delay", - 10126 : "Country standard set", - 10127 : "Device name", - 10128 : "Device class", - 10129 : "Device type", - 10130 : "Manufacturer", - 10134 : "Set total operating time at grid connection point", - 10135 : "Set total feed-in time at the grid connection pt.", - 10136 : "Set fan operating time", - 10137 : "Set fan2 operating time", - 10138 : "Set heat sink fan operating time", - 10139 : "Set transfomer fan operating time", - 10140 : "Set transformer fan 2 operating time", - 10141 : "Reset operating data", - 10143 : "Load parameter", - 10144 : "Memory card function", - 10145 : "Start of derating based on external temperature", - 10146 : "Start of derating based on external temperature 2", - 10147 : "Start of derating based on interior temperature", - 10148 : "Setpoint of the interior temperature", - 10149 : "Start of derating based on heat sink temperature", - 10150 : "Setpoint of the heat sink temperature", - 10151 : "Start of derating based on heat sink temperature 2", - 10152 : "Setpoint of the heat sink temperature 2", - 10153 : "Start of derating based on transformer temperature", - 10154 : "Setpoint of transformer temperature", - 10155 : "Start of derating based on board temperature", - 10156 : "Start of derating based on inverter temperature", - 10159 : "Set active power limit", - 10160 : "Current power limit A", - 10161 : "Power limit B", - 10162 : "Power limit C", - 10163 : "Power limitation", - 10164 : "Phase assignment", - 10165 : "Start. point of the power control via frequency", - 10166 : "End point of the power control via frequency", - 10167 : "Tripping threshold DC current monitoring", - 10168 : "Tripping time DC current monitoring", - 10169 : "Maximum duration of a short interruption", - 10170 : "Reconnection time upon short interruption", - 10171 : "Reconnection time upon grid interruption", - 10172 : "Reconnection time upon restart", - 10173 : "Escalation factor", - 10174 : "Frequency monitoring upper maximum threshold", - 10175 : "Frq. monitoring upper max. threshold trip. time", - 10176 : "Frequency monitoring median maximum threshold", - 10177 : "Frq. monitoring median max. threshold trip. time", - 10178 : "Frequency monitoring lower maximum threshold", - 10179 : "Frq. monitoring lower max. threshold trip. time", - 10180 : "Frequency monitoring upper minimum threshold", - 10181 : "Frq. monitoring upper min. threshold trip. time", - 10182 : "Frequency monitoring median minimum threshold", - 10183 : "Frq. monitoring median min. threshold trip. time", - 10184 : "Frequency monitoring lower minimum threshold", - 10185 : "Frq. monitoring lower min. threshold trip. time", - 10186 : "Voltage monitoring upper maximum threshold", - 10187 : "Voltage monitoring upper max. threshold trip. time", - 10188 : "Voltage monitoring median maximum threshold", - 10189 : "Voltage monitoring median max. threshold trip.time", - 10190 : "Voltage monitoring lower maximum threshold", - 10191 : "Voltage monitoring lower max. threshold trip. time", - 10192 : "Voltage monitoring lower minimum threshold", - 10193 : "Voltage monitoring lower min. threshold trip. time", - 10194 : "Voltage monitoring of median minimum threshold", - 10195 : "Voltage monitoring median min. threshold trip.time", - 10196 : "Voltage monitoring upper minimum threshold", - 10197 : "Voltage monitoring upper min. threshold trip. time", - 10198 : "Voltage increase protection", - 10200 : "Maximum Bluetooth power", - 10201 : "Set country standard", - 10202 : "DC grounding monitoring", - 10203 : "Minimum insulation resistance", - 10204 : "Production test mode", - 10207 : "Data recording on memory card", - 10209 : "DC voltage input", - 10210 : "DC voltage A input", - 10211 : "DC voltage B input", - 10212 : "DC voltage C input", - 10213 : "DC current input", - 10214 : "DC current A input", - 10215 : "DC current B input", - 10216 : "DC current C input", - 10217 : "DC power input", - 10218 : "DC power A input", - 10219 : "DC power B input", - 10220 : "DC power C input", - 10221 : "Operating condition DC current input", - 10222 : "Operating condition DC voltage input", - 10223 : "Operating condition DC power input", - 10224 : "Highest measured DC voltage", - 10225 : "Maximum DC voltage A", - 10226 : "Maximum DC voltage B", - 10227 : "Maximum DC voltage C", - 10228 : "DC current A input", - 10229 : "DC current A input", - 10230 : "DC current A input", - 10231 : "DC current A input", - 10232 : "DC current A input", - 10233 : "DC current B input", - 10241 : "Start delay input", - 10242 : "Minimum voltage input", - 10243 : "Maximum allowed voltage input", - 10244 : "Maximum allowed voltage input A", - 10245 : "Maximum allowed voltage input B", - 10246 : "Maximum allowed voltage input C", - 10247 : "Constant voltage setpoint", - 10248 : "Constant voltage setpoint A", - 10249 : "Constant voltage setpoint B", - 10250 : "Constant voltage setpoint C", - 10257 : "Grid nominal voltage", - 10258 : "Communication version", - 10259 : "Set total yield", - 10260 : "Set absorbed energy", - 10261 : "Set highest measured ambient temperature", - 10263 : "Set highest measured internal temperature", - 10264 : "Set highest measured heat sink temperature", - 10265 : "Set highest measured heat sink temperature 2", - 10266 : "Set highest measured transformer temperature", - 10267 : "Set highest measured inverter temperature", - 10268 : "Set highest measured PCB temperature", - 10269 : "Set highest measured external temperature", - 10270 : "Set highest measured external temperature 2", - 10272 : "Day yield", - 10273 : "Set number of grid connections", - 10274 : "Temporal control of the power limitation", - 10275 : "Reset operating data (for Service)", - 10276 : "Set highest measured module temperature", - 10277 : "Reset measured values", - 10278 : "System time", - 10283 : "Checking firmware", - 10284 : "Set user password", - 10285 : "Set installer password", - 10286 : "Set service password", - 10287 : "Set developer password", - 10288 : "Number of plant detections", - 10289 : "Time of the last detection", - 10290 : "Hardware on Interface 1", - 10291 : "Hardware on Interface 2", - 10292 : "Hardware on Interface 3", - 10297 : "DHCP DNS Server IP", - 10298 : "DHCP Gateway IP", - 10299 : "DHCP IP address", - 10300 : "DHCP server configuration owner", - 10301 : "DHCP Subnet mask", - 10302 : "WAN IP", - 10303 : "Provider IP", - 10306 : "Daylight Saving Time on", - 10308 : "Date format of the user interface", - 10309 : "Language of the user interface", - 10310 : "Units of length of the user interface", - 10311 : "Number format of the user interface", - 10312 : "Unit of temperature of the user interface", - 10313 : "Time format of the user interface", - 10314 : "Standard/Daylight saving time conversion on", - 10315 : "Automatic time synchronization", - 10316 : "Time zone", - 10317 : "Automatic updates activated", - 10318 : "Time of the automatic update", - 10319 : "Device updates activated", - 10320 : "Ethernet DHCP activated", - 10321 : "Ethernet DNS server", - 10322 : "Ethernet gateway", - 10323 : "Ethernet IP address", - 10324 : "Ethernet subnet mask", - 10325 : "Ethernet NAT port", - 10326 : "Ethernet proxy activated", - 10327 : "Ethernet proxy server login", - 10328 : "Ethernet proxy server port", - 10329 : "Ethernet proxy server password", - 10330 : "Ethernet proxy server address", - 10331 : "Web service Port", - 10332 : "HTTP server port", - 10333 : "Test modem connection", - 10334 : "GPRS-APN", - 10335 : "Dial-in number for modem connection", - 10336 : "Password for modem connection", - 10337 : "Modem SIM Card PIN", - 10338 : "Test modem signal strength", - 10339 : "Upload data to the portal", - 10340 : "Result of the last upload", - 10341 : "Test the connection to the portal", - 10342 : "Result of the last connection test", - 10343 : "Register", - 10344 : "Result of the last registration", - 10345 : "Portal user name", - 10346 : "Email address of portal user", - 10347 : "Plant name in portal", - 10348 : "Plant ID in portal", - 10349 : "Use Sunny Portal", - 10350 : "Frequency of data uploads to the portal", - 10351 : "Status of the last SunnyDNS operation", - 10352 : "SunnyDNS active", - 10353 : "SunnyDNS Password", - 10354 : "FTP Push active", - 10355 : "FTP Push: Connection test", - 10356 : "FTP Push Login", - 10357 : "FTP Push server Port", - 10358 : "FTP Push Password", - 10359 : "FTP Push Server Address", - 10362 : "GPRS-Always-On active", - 10363 : "Firmware version of the module", - 10364 : "Hardware version of the module", - 10365 : "Revision status of the module", - 10366 : "Update version of the module", - 10367 : "Serial number of the module", - 10368 : "SUSyID of the module", - 10373 : "Software package", - 10374 : "Find device", - 10375 : "Firmware version of the central assembly", - 10376 : "Hardware version of the central assembly", - 10377 : "Revision status of the central assembly", - 10378 : "Update version of the central assembly", - 10379 : "Serial number of the central assembly", - 10380 : "SUSyID of the central assembly", - 10381 : "Firmware version of the communication assembly", - 10382 : "Hardware version of the communication assembly", - 10383 : "Revision status of the communication assembly", - 10384 : "Update version of the communication assembly", - 10385 : "Serial number of the communication assembly", - 10386 : "SUSyID of the communication assembly", - 10387 : "Firmware version of the residual current mon. unit", - 10388 : "Hardware version of the residual current mon. unit", - 10389 : "Revision status of the residual current mon. unit", - 10390 : "Update version of the residual current mon. unit", - 10391 : "Serial number of residual current monitoring unit", - 10392 : "SUSyID of the residual current monitoring unit", - 10393 : "Firmware version of the display", - 10394 : "Hardware version of the display", - 10395 : "Revision status of the display", - 10396 : "Update version of the display", - 10397 : "Serial number of the display", - 10398 : "SUSyID of the display", - 10399 : "Firmware version of the logic component", - 10400 : "Hardware version of the logic component", - 10401 : "Revision status of the logic component", - 10402 : "Update version of the logic component", - 10403 : "Serial number of the logic component", - 10404 : "SUSyID of the logic component", - 10405 : "Firmware version of the RS485 Module", - 10406 : "Hardware version of the RS485 module", - 10407 : "Revision status of the RS485 module", - 10408 : "Update version of the RS485 module", - 10409 : "Serial number of the RS485 module", - 10410 : "SUSyID of the RS485 module", - 10411 : "Firmware version of the Zigbee components", - 10412 : "Hardware version of the Zigbee components", - 10413 : "Revision status of the Zigbee components", - 10414 : "Update version of the Zigbee components", - 10415 : "Serial number of the Zigbee components", - 10416 : "SUSyID of the Zigbee components", - 10417 : "Firmware version of the Bluetooth component", - 10418 : "Hardware version of the Bluetooth component", - 10419 : "Revision status of the Bluetooth component", - 10420 : "Update version of the Bluetooth component", - 10421 : "Serial number of the Bluetooth component", - 10422 : "SUSyID of the Bluetooth component", - 10423 : "Firmware version of the operating system", - 10424 : "Hardware version of the operating system", - 10425 : "Revision status of the operating system", - 10426 : "Update version of the operating system", - 10427 : "Serial number of the operating system", - 10428 : "SUSyID of the operating system", - 10429 : "Plant name", - 10430 : "Sunny Portal server address", - 10431 : "Time difference Plant/System", - 10432 : "Number of S0 impulses", - 10433 : "Consumed energy", - 10434 : "Number of Resets", - 10435 : "Power absorbed", - 10436 : "Reset operating data for string failure detection", - 10437 : "Operating mode of string failure detection", - 10438 : "Op. mode of stat.V stab., stat.V stab. config.", - 10439 : "Operating mode of feed-in management", - 10440 : "Operating mode of active power reduction in case of overfrequency P(f)", - 10441 : "Status, plant control", - 10443 : "Difference until next characteristic curve value", - 10444 : "Difference until next charact. curve value Time", - 10445 : "Nominal voltage offset", - 10446 : "Gradient of reactive power characteristic curve", - 10448 : "Reactive power setpoint in var", - 10449 : "Reactive power set value as a %", - 10451 : "Reactive power value starting point", - 10452 : "Active power value starting point", - 10453 : "Reactive power value end point", - 10454 : "Active power value end point", - 10455 : "cosPhi setpoint, cosPhi config., direct specif.", - 10456 : "cosPhi excit.type, cosPhi config., direct spec.", - 10457 : "Excit. type at start point, cosPhi(P) char. conf.", - 10458 : "cosPhi at start point, cosPhi(P) char. config.", - 10459 : "Active power starting point", - 10460 : "Excit. type at end point, cosPhi(P) char. config.", - 10461 : "cosPhi at end point, cosPhi(P) char. config.", - 10462 : "Active power end point", - 10463 : "Active power limitation P, active power configuration", - 10464 : "Active power limitation P, active power configuration", - 10466 : "Difference between starting frequency and grid frequency, linear instantaneous power gradient configuration", - 10467 : "Active power gradient, linear instantaneous power gradient configuration", - 10468 : "Difference between reset frequency and grid frequency, linear instantaneous power gradient configuration", - 10469 : "Activation of stay-set indicator function, linear instantaneous power gradient configuration", - 10471 : "Current reactive power limit", - 10472 : "Max. reactive power", - 10473 : "Currently set apparent power limit", - 10474 : "Maximum apparent power device", - 10475 : "Current cosPhi limit", - 10476 : "Min. cosPhi", - 10477 : "Reconnect gradient after grid fault", - 10478 : "Activation of active power gradient for reconnection after grid fault", - 10479 : "Active power gradient", - 10480 : "Activation of active power gradient", - 10481 : "Firmware version of string protection", - 10482 : "Hardware version of string protection", - 10483 : "Revision status of the string protection", - 10484 : "Update version of the string protection", - 10485 : "String protection serial number", - 10486 : "SUSyID of string protection", - 10487 : "Status, device control", - 10488 : "Normalized total apparent power", - 10489 : "Boost converter temperature", - 10490 : "Highest measured boost converter temperature", - 10491 : "Boost converter 2 temperature", - 10492 : "Highest measured boost converter 2 temperature", - 10493 : "Start boost converter temperature derating", - 10494 : "Set highest measured boost converter temperature", - 10495 : "Set highest measured boost converter temperature 2", - 10496 : "Maximum allowable phase shift", - 10497 : "Tripping time when exceeding max. phase shift", - 10498 : "Maximum allowable frequency drift", - 10499 : "Tripping time when exceeding max. frequency drift", - 10500 : "Lower frequency for reconnection", - 10501 : "Upper frequency for reconnection", - 10502 : "Nominal frequency", - 10503 : "Calibration voltage", - 10504 : "Calibration status", - 10505 : "Selection of the voltage(s) to be calibrated", - 10506 : "Maximum module ground current", - 10507 : "Tripping time maximum module ground current", - 10508 : "Module grounding prescribed?", - 10509 : "Prescribed module grounding type", - 10510 : "Module grounding status", - 10511 : "Firmware version of protocol converter", - 10512 : "Hardware version of protocol converter", - 10513 : "Revision status of the protocol converter", - 10514 : "Update version of the protocol converter", - 10515 : "Serial number of the protocol converter", - 10516 : "SUSyID of protocol converter", - 10517 : "Set plant time", - 10518 : "Synchronize time with portal", - 10519 : "Syslog service activated until", - 10583 : "Reactive power limitation by plant control", - 10584 : "Normalized reactive power limitation by plant ctrl", - 10585 : "Active power limitation by plant control", - 10586 : "Normalized active power limitation by plant ctrl", - 10587 : "Dis.pow.factor that can be changed via plant ctrl", - 10588 : "Excitation type that can be changed by plant ctrl", - 10589 : "Time-out for communication fault indication", - 10590 : "Measurement name in local language", - 10591 : "Events in local language", - 10610 : "Cycle time of the OptiTrac Global Peak algorithm", - 10611 : "Power limit of the OptiTrac Global Peak", - 10612 : "OptiTrac Global Peak switched on", - 10637 : "Setpoint for PV voltage", - 10638 : "Derating status", - 10639 : "Setpoint for intermediate circuit voltage", - 10640 : "Path for update file", - 10641 : "DAA type ID", - 10647 : "RAA type ID", - 10648 : "Min. voltage for reconnection", - 10649 : "Max. voltage for reconnection", - 10650 : "Specified voltage UQ0, reactive power/voltage characteristic curve configuration Q(U)", - 10651 : "Symmetrical limit for maximum reactive power, reactive power/voltage characteristic curve configuration Q(U)", - 10652 : "Voltage spread, reactive power/voltage characteristic curve configuration Q(U)", - 10653 : "Reactive power gradient, reactive power/voltage characteristic curve configuration Q(U)", - 10654 : "Adjustment time for characteristic operating point, reactive power/voltage characteristic curve configuration Q(U)", - 10655 : "Act. power at start point, cosPhi(P) char. config.", - 10656 : "Act. power at end point, cosPhi(P) char. config.", - 10660 : "Reference voltage, plant control", - 10661 : "Reactive power gradient", - 10662 : "Reference correction voltage, plant control", - 10663 : "PWM inverse voltage, dynamic grid support configuration", - 10664 : "PWM inversion delay, dynamic grid support configuration", - 10665 : "Reactive current droop, full dynamic grid support configuration", - 10666 : "Gradient K or reactive current droop, full dynamic grid support configuration", - 10667 : "Check for update and install it", - 10668 : "Hysteresis voltage, dynamic grid support configuration", - 10669 : "CPU monitor", - 10670 : "CPU load", - 10671 : "FTP Push server path", - 10672 : "IRE status", - 10673 : "Number of DC disconnects", - 10674 : "Lower limit, voltage dead band, full dynamic grid support configuration", - 10675 : "Upper limit, voltage dead band, full dynamic support configuration", - 10676 : "Result of the last FTP-Push connection test", - 10677 : "Operating mode of dynamic grid support, dynamic grid support configuration", - 10678 : "Target version of the software package", - 10679 : "Update version of the software package", - 10680 : "Measures in the case of a grounding error", - 10681 : "FTP Push: measurement name in local language", - 10682 : "FTP Push: data export in CSV format", - 10683 : "FTP Push: data export in XML format", - 10684 : "Data export in CSV format", - 10685 : "Data export in XML format", - 10686 : "Displacement power factor", - 10687 : "Reactive power droop mode, reactive power/voltage characteristic curve configuration Q(U)", - 10688 : "Status of islanding detection frequency monitor", - 10689 : "Tripping time of islanding detection frq. monitor", - 10690 : "Status of islanding detection unbalance detection", - 10691 : "Permissible grid unbalance of islanding detection", - 10692 : "Trip.time of islanding detection unbalance detect.", - 10693 : "Operating mode of multifunction relay", - 10694 : "Minimum On time for MFR self-consumption", - 10695 : "Minimum On power for MFR self-consumption", - 10696 : "Minimum power On time, MFR self-consumption", - 10697 : "Initiate device restart", - 10698 : "Status of MFR with control via communication", - 10699 : "Constant deviation from power calculation", - 10700 : "Pre-expon. factor of power consumption acc. to Udc", - 10701 : "Pre-expon. factor of power cons. acc. to Udc^2", - 10702 : "Pre-expon. factor of power cons. Acc. to Udc^3", - 10703 : "Proportionate factor of power control", - 10704 : "Integral factor of power control", - 10705 : "Differential factor of power control", - 10706 : "Critical voltage to end feed-in", - 10707 : "Minimum On power for MFR battery bank", - 10708 : "Minimum time before reconnection of MFR battery bank", - 10709 : "Login required for GridGuard parameter", - 10710 : "Displacement power factor", - 10711 : "Excitation type of cosPhi", - 10712 : "Energy counter type", - 10713 : "PV generation counter reading", - 10714 : "Grid feed-in counter reading", - 10715 : "Grid reference counter reading", - 10716 : "PV power generated", - 10717 : "Power grid feed-in", - 10718 : "Power grid reference", - 10719 : "Perm. grid-frequency deviation of islanding detection", - 10720 : "Current pulse height of islanding detection", - 10721 : "Max. impedance gradient of islanding detection", - 10722 : "Status of impedance of islanding detection", - 10723 : "Amplitude of islanding detection", - 10724 : "Frequency of islanding detection", - 10725 : "Status of passive islanding detection", - 10726 : "Voltage monitoring normalized lower maximum threshold", - 10727 : "Voltage monitoring normalized upper minimum threshold", - 10728 : "Norm. max. voltage for reconnecting", - 10729 : "Norm. min. voltage for reconnecting", - 10730 : "Correction voltage, voltage increase protection", - 10731 : "CO2-saving", - 10732 : "Factor for CO2-saving", - 10733 : "Grid type", - 10734 : "Grid impedance", - 10735 : "Central point of P-coordinates turbine mode", - 10736 : "Lower voltage limit feed-in, turbine mode", - 10737 : "Central point of U-coordinates turbine mode", - 10739 : "Start point of U-coordinates turbine mode", - 10740 : "Power gradient for start-up, turbine mode", - 10741 : "Ripple control signal detection threshold", - 10742 : "Ripple control signal detection frequency", - 10743 : "Ripple control signal detection operating mode", - 10744 : "Ground voltage", - 10745 : "DC converter HW version", - 10746 : "DC converter SW version", - 10747 : "Backup mode operating mode", - 10748 : "Backup mode status", - 10749 : "PowerBalancer operating mode", - 10750 : "Max. load unbalance for PowerBalancer", - 10751 : "S0-pulses PV feed-in counter", - 10752 : "S0-pulses grid feed-in counter", - 10753 : "S0-pulses grid reference counter", - 10754 : "GridGuard version", - 10756 : "Consumer power", - 10757 : "Rise in self-consumption", - 10758 : "Rise in self-consumption today", - 10759 : "PV mains connection", - 10760 : "Power supply status", - 10761 : "Number of battery charge throughputs", - 10764 : "SSM Id for the comm. fault has occurred", - 10765 : "SMU warning code for string fault", - 10766 : "Status of signal contact 1", - 10767 : "Status of signal contact 2", - 10768 : "Operating mode of the device update", - 10769 : "Update source of the device update", - 10770 : "Status of the device update", - 10771 : "Transmission attempts of a device update", - 10772 : "Time of last transm. attempt of a device update", - 10773 : "S0 pulses per kWh for PV generation counter", - 10774 : "S0 pulses per kWh for feed counter", - 10775 : "S0 pulses per kWh for reference counter", - 10776 : "Update operating mode", - 10777 : "Status after loss of communication in autom. mode", - 10778 : "Status after switching on automatic", - 10779 : "Status of the grid switch", - 10781 : "Automatic mode of the grid switch", - 10782 : "Timeout after loss of communication", - 10783 : "Starting current detection", - 10784 : "Gradient K of the reactive current droop, full dynamic grid support configuration", - 10785 : "Automatic mode can be activated", - 10786 : "Meter reading consumption meter", - 10788 : "Grid voltage phase L1 against L2", - 10792 : "Logical flow direction phase L1", - 10793 : "Logical flow direction phase L2", - 10795 : "Grid disconn. at 0% specif. by feeding management", - 10796 : "Characteristic curve number of the plant control procedure P(U)", - 10797 : "Adjustment time of characteristic operating point, conf. of grid integr. char. 1", - 10798 : "Decrease ramp, conf. of grid integr. char. 1", - 10799 : "Increase ramp, conf. of grid integr. char. 1", - 10800 : "Number of points to be used, conf. of grid integr. char. 1", - 10801 : "X value 1, conf. of grid integr. char. 1", - 10802 : "Y value 1, conf. of grid integr. char. 1", - 10803 : "X value 2, conf. of grid integr. char. 1", - 10804 : "Y value 2, conf. of grid integr. char. 1", - 10805 : "X value 3, conf. of grid integr. char. 1", - 10806 : "Y value 3, conf. of grid integr. char. 1", - 10807 : "X value 4, conf. of grid integr. char. 1", - 10808 : "Y value 4, conf. of grid integr. char. 1", - 10809 : "X value 5, conf. of grid integr. char. 1", - 10810 : "Y value 5, conf. of grid integr. char. 1", - 10811 : "X value 6, conf. of grid integr. char. 1", - 10812 : "Y value 6, conf. of grid integr. char. 1", - 10813 : "Active power gradient after reset frequency, linear instantaneous power gradient configuration", - 10814 : "Active power gradient connection", - 10818 : "E-mail alert function on", - 10820 : "E-mail address(es) for alert", - 10821 : "Test e-mail for e-mail alert", - 10824 : "Modbus TCP server on", - 10825 : "Modbus TCP server port", - 10826 : "Modbus UDP server on", - 10827 : "Modbus UDP server port", - 10828 : "DHCP server switched on", - 10829 : "Speedwire DHCP server start IP address", - 10830 : "Speedwire DHCP server end IP address", - 10831 : "Speedwire DHCP server subnet mask", - 10832 : "Speedwire DHCP server IP address", - 10833 : "Time synchronisation source", - 10834 : "NTP server", - 10837 : "Analogue current input 1 (AI1)", - 10838 : "Analogue current input 2 (AI2)", - 10839 : "Analogue current input 3 (AI3)", - 10840 : "Analogue voltage input 1 (AI1)", - 10842 : "AFCI switched on", - 10843 : "Set energy taken up by consumers", - 10844 : "Conn. point of counter on measuring interface 1", - 10845 : "Conn. point of counter on measuring interface 2", - 10846 : "Conn. point of counter on measuring interface 3", - 10847 : "Type of counter on measuring interface 1", - 10848 : "Type of counter on measuring interface 2", - 10849 : "Type of counter on measuring interface 3", - 10850 : "Logical flow direction phase L3", - 10852 : "Char. of insolation sensor - min. insolation", - 10853 : "Char. of insolation sensor - max. insolation", - 10854 : "Char. of insolation sensor - min. measurement", - 10855 : "Char. of insolation sensor - max. measurement", - 10856 : "Free memory on USB medium", - 10857 : "Free memory on USB medium 2", - 10858 : "Fast shut-down", - 10861 : "Type of central assembly", - 10862 : "Type of communication assembly", - 10863 : "Type of residual current monitoring", - 10864 : "Type of display", - 10865 : "Type of logic component", - 10866 : "Type of RS485 module", - 10867 : "Type of Zigbee components", - 10868 : "Type of Bluetooth component", - 10869 : "Type of operating system", - 10870 : "Type of string protection", - 10871 : "Type of protocol converter", - 10872 : "Type of module in module slot", - 10873 : "Key switch", - 10874 : "Local time", - 10875 : "DC switch", - 10876 : "Error message DC switch", - 10877 : "String status", - 10878 : "Speedwire connection status of SMACOM A", - 10879 : "Connection speed of SMACOM A", - 10880 : "Speedwire connection status of SMACOM B", - 10881 : "Connection speed of SMACOM B", - 10882 : "Current speedwire IP address", - 10883 : "Current speedwire subnet mask", - 10884 : "Current speedwire gateway address", - 10885 : "Current speedwire DNS server address", - 10886 : "Status of the Webconnect functionality", - 10887 : "Webconnect functionality switched on", - 10888 : "MAC address", - 10889 : "Automatic speedwire configureation switched on", - 10890 : "Speedwire IP address", - 10891 : "Speedwire subnet mask", - 10892 : "Speedwire gateway address", - 10893 : "Speedwire DNX server address", - 10894 : "Power PV generation (caluclated)", - 10895 : "Counter status PV generation counter (calculated)", - 10896 : "Duplex mode of SMACOM A", - 10897 : "Duplex mode of SMACOM B", - 10898 : "Amp hours counter for battery charge", - 10899 : "Amp hours counter for battery discharge", - 10900 : "Active battery charging mode", - 10901 : "Current generator power", - 10902 : "Battery maint. charge status", - 10903 : "Current battery charge status", - 10904 : "Battery temperature", - 10905 : "Battery voltage", - 10906 : "Absorbed energy", - 10907 : "Released energy", - 10908 : "Automatic generator start", - 10909 : "Reason for generator request", - 10910 : "Released generator power", - 10911 : "Manual generator control", - 10912 : "Generator operating hours", - 10913 : "Generator shutdown battery charge limit", - 10914 : "Generator startup battery charge limit", - 10915 : "Number of generator starts", - 10916 : "Grid creating generator", - 10917 : "Multifunction relay status", - 10918 : "Energy consumed internally", - 10919 : "Current rise in self-consumption", - 10920 : "Current self-consumption", - 10921 : "Current battery capacity", - 10922 : "Battery current", - 10923 : "Battery quick charge time", - 10924 : "Battery compensation charge time", - 10925 : "Battery full charge time", - 10926 : "Max. start attempts after error", - 10927 : "Max. battery charging current", - 10928 : "Current battery charging set voltage", - 10929 : "Rated battery capacity", - 10930 : "Max. battery temperature", - 10931 : "Battery type", - 10932 : "Rated battery voltage", - 10933 : "Acknowledge generator errors", - 10934 : "Rated generator current", - 10935 : "Generator request via power on", - 10936 : "Generator shutdown load limit", - 10937 : "Generator startup load limit", - 10938 : "Generator status", - 10939 : "Rise in self-consumption switched on", - 10940 : "Grid feed-in today", - 10941 : "Power outage", - 10942 : "Number of DC current measurement units", - 10943 : "Free memory on USB medium 1", - 10944 : "External measurement of the insulation resistance", - 10945 : "IP address of the SMTP server", - 10946 : "SMTP server port", - 10947 : "User name for registration on the SMTP server", - 10948 : "Password for registration on SMTP server", - 10949 : "Type of password encryption", - 10950 : "Synchronise with time synchronisation source", - 10951 : "SSH switched on", - 10952 : "IGMP switched on", - 10953 : "Speedwire Group", - 10954 : "Analogue current input 4", - 10955 : "Analogue voltage input 2", - 10956 : "Analogue voltage input 3", - 10957 : "Analogue voltage input 4", - 10958 : "Encrypt portal communication", - 10959 : "Portal communication monitoring signal", - 10960 : "Last successful portal upload", - 10961 : "Hardware ID", - 10962 : "Data logging on monitoring server", - 10963 : "Remove device", - 10964 : "Remove all devices", - 10965 : "WebConnect system environment", - 10966 : "Wind direction", - 10967 : "Reset communication data", - 10968 : "Alarm at active power limit", - 10969 : "Alarm at reactive power specification", - 10970 : "Result of the last e-mail dispatch", - 10971 : "X value 7, conf. of grid integr. char. 1", - 10972 : "Y value 7, conf. of grid integr. char. 1", - 10973 : "X value 8, conf. of grid integr. char. 1", - 10974 : "Y value 8, conf. of grid integr. char. 1", - 10975 : "Characteristic number, conf. of reactive power/voltage char. Q(U)", - 10976 : "Activating active power, conf. of reactive power/voltage char. Q(U)", - 10977 : "Deactivating active power, conf. of reactive power/voltage char. Q(U)", - 10978 : "Waiting time of active power grad. after reset frequency, conf. of linear instantaneous power gradient", - 10979 : "Activating voltage, cosPhi(P) char. conf.", - 10980 : "Deactivating voltage, cosPhi(P) char. conf.", - 10981 : "X-axes reference, conf. of grid integration char. 1", - 10982 : "Y-axes reference, conf. of grid integration char. 1", - 10983 : "Adjustment time of char. operating point, conf. of grid integration char. 2", - 10984 : "Decrease ramp, conf. of grid integration char. 2", - 10985 : "Increase ramp, conf. of grid integration char. 2", - 10986 : "Number of points to be used, conf. of grid integr. char. 2", - 10987 : "Input unit, conf. of grid integration char. 2", - 10988 : "Output frequency, conf. of grid integration char. 2", - 10989 : "X value 1, conf. of grid integr. char. 2", - 10990 : "X value 2, conf. of grid integr. char. 2", - 10991 : "X value 3, conf. of grid integr. char. 2", - 10992 : "X value 4, conf. of grid integr. char. 2", - 10993 : "X value 5, conf. of grid integr. char. 2", - 10994 : "X value 6, conf. of grid integr. char. 2", - 10995 : "X value 7, conf. of grid integr. char. 2", - 10996 : "X value 8, conf. of grid integr. char. 2", - 10997 : "Y value 1, conf. of grid integr. char. 2", - 10998 : "Y value 2, conf. of grid integr. char. 2", - 10999 : "Y value 3, conf. of grid integr. char. 2", - 11000 : "Y value 4, conf. of grid integr. char. 2", - 11001 : "Y value 5, conf. of grid integr. char. 2", - 11002 : "Y value 6, conf. of grid integr. char. 2", - 11003 : "Y value 7, conf. of grid integr. char. 2", - 11004 : "Y value 8, conf. of grid integr. char. 2", - 11005 : "Speedwire connection status of SMACOM C", - 11006 : "Connection speed of SMACOM C", - 11007 : "Speedwire connection status of SMACOM D", - 11008 : "Connection speed of SMACOM D", - 11009 : "Duplex mode of SMACOM C", - 11010 : "Duplex mode of SMACOM D", - 11011 : "Operating mode of power control module", - 11012 : "Status of digital inputs of power control module", - 11013 : "Lower frequency limit prior to end of active power reduction, linear instant. power gradient conf.", - 11014 : "Upper frequency limit prior to end of active power reduction, linear instant. power gradient conf.", - 11015 : "Goose application ID", - 11016 : "Frequency monitoring switchable max. threshold", - 11017 : "Frequency monit. switchable max. threshold tripping time", - 11018 : "Frequency monitoring switchable min. threshold", - 11019 : "Frequency monit. switchable min. threshold tripping time", - 11020 : "Operating mode of frequency restriction", - 11021 : "Source of quick shut-down", - 11022 : "Frequency band narrowing", - 11023 : "Alarm upon warnings", - 11024 : "Alarm e-mail languages", - 11025 : "Alternative e-mail sender address (optional)", - 11027 : "Normalized active power limitation by plant ctrl", - 11028 : "Normalized reactive power limitation by plant ctrl", - 11029 : "Digital input group 1 (DI1 .. DI4)", - 11030 : "Digital input group 2 (DI5 .. DI8)", - 11031 : "Grid voltage phase L2 against L3", - 11032 : "Grid voltage phase L3 against L1", - 11033 : "Power unit supplies data", - 11034 : "Voltage increase protection trigger time", - 11035 : "Goose-Mac address", - 11036 : "Grid connection point rated current", - 11037 : "Active power specif. by plant control", - 11038 : "Reactive power specif. by plant control", - 11039 : "Active power limitation by plant control", - 11040 : "Operating status", - 11041 : "RCD adjustment", - 11042 : "Sunny portal port", - 11043 : "Nominal plant power", - 11044 : "Mode of act. power limit. at grid connection pt", - 11045 : "Dynamic act. power limitat. at grid connection pt", - 11046 : "Set active power limit at grid connection point", - 11047 : "Set active power limit at grid connection point", - 11048 : "Plant control ON", - 11050 : "Number of section switches", - 11051 : "Time to open the section switches", - 11052 : "Time to close section switches", - 11053 : "Generator operating hours", - 11054 : "Generator output energy", - 11055 : "Current generator performance", - 11056 : "Battery discharge cut-off voltage", - 11057 : "Maximum battery charging current", - 11058 : "Maximum battery discharge current", - 11059 : "Status of utility grid", - 11060 : "Cell charge nominal voltage for boost charge", - 11061 : "Cell charge nominal voltage for full charging", - 11062 : "Cell charge nominal voltage for equalisation", - 11063 : "Cell charge nominal voltage for trickle charge", - 11064 : "Voltage monitoring hysteresis minimum threshold", - 11065 : "Voltage monitoring hysteresis maximum threshold", - 11066 : "Frequency monitoring hysteresis minimum threshold", - 11067 : "Frequency monitoring hysteresis maximum threshold", - 11068 : "Voltage monit. gener. lower minimum threshold", - 11069 : "Voltage monit. gener. upper maximum threshold", - 11070 : "Voltage monit. gener. hysteresis min. threshold", - 11071 : "Voltage monit. hysteresis generator max. threshold", - 11072 : "Frequency monit. generator lower minimum threshold", - 11073 : "Frequency monit. generator without max. threshold", - 11074 : "Frequency monit. gener. hysteresis min. threshold", - 11075 : "Freq. Monit. generator hysteresis max. threshold", - 11076 : "Voltage monitoring generator maximum reverse power", - 11077 : "Volt. monit. gener. max. reverse power trip. time", - 11078 : "Output external power connection", - 11079 : "Output external power connection phase A", - 11080 : "Output external power connection phase B", - 11081 : "Output external power connection phase C", - 11082 : "Reactive power external power connection", - 11083 : "Reactive power external power connection phase A", - 11084 : "Reactive power external power connection phase B", - 11085 : "Reactive power external power connection phase C", - 11086 : "Grid frequency of external power connection", - 11087 : "Voltage external power connection phase A", - 11088 : "Voltage external power connection phase B", - 11089 : "Voltage external power connection phase C", - 11090 : "Electricity external power connection phase A", - 11091 : "Electricity external power connection phase B", - 11092 : "Electricity external power connection phase C", - 11093 : "Operating state grid voltage L1 against L2", - 11094 : "Operating state grid voltage L2 against L3", - 11095 : "Operating state grid voltage L3 against L1", - 11096 : "Number of UCP events", - 11097 : "Derating because of low DC voltage", - 11098 : "Derating because of power and DC voltage", - 11099 : "Bias voltage phase L1", - 11100 : "Bias voltage phase L2", - 11101 : "Relative bias voltage", - 11102 : "Rated apparent power of all inverters", - 11103 : "Ohmic resistive coating of the low-voltage line", - 11104 : "Induc. reactive coating of the low-volt.power line", - 11105 : "Length of the low-voltage cabling", - 11106 : "Ohmic resistive coating of the medium-voltage line", - 11107 : "Capac. resistive coating of the medium-volt. line", - 11108 : "Length of the medium-voltage cabling", - 11109 : "Nominal apparent power of the transformer", - 11110 : "Short-circuit voltage of the transformer", - 11111 : "Nominal voltage of the high-voltage side", - 11112 : "Serial number of the counter on meas. interface 1", - 11113 : "Serial number of the counter on meas. interface 2", - 11114 : "Serial number of the counter on meas. interface 3", - 11115 : "PLC communication package error rate", - 11116 : "Firmware version of the module", - 11117 : "Hardware version of the module", - 11118 : "Revision status of the module", - 11119 : "Update version of the module", - 11120 : "Serial number of the module", - 11121 : "SUSyID of module", - 11122 : "Type of module in the module shaft", - 11123 : "Power control module D1: 0 | D2:0 | D3: 0 | D4: 0", - 11124 : "Power control module D1: 1 | D2:0 | D3: 0 | D4: 0", - 11125 : "Power control module D1: 0 | D2:1 | D3: 0 | D4: 0", - 11126 : "Power control module D1: 1 | D2:1 | D3: 0 | D4: 0", - 11127 : "Power control module D1: 0 | D2:0 | D3: 1 | D4: 0", - 11128 : "Power control module D1: 1 | D2:0 | D3: 1 | D4: 0", - 11129 : "Power control module D1: 0 | D2:1 | D3: 1 | D4: 0", - 11130 : "Power control module D1: 1 | D2:1 | D3: 1 | D4: 0", - 11131 : "Power control module D1: 0 | D2:0 | D3: 0 | D4: 1", - 11132 : "Power control module D1: 1 | D2:0 | D3: 0 | D4: 1", - 11133 : "Power control module D1: 0 | D2:1 | D3: 0 | D4: 1", - 11134 : "Power control module D1: 1 | D2:1 | D3: 0 | D4: 1", - 11135 : "Power control module D1: 0 | D2:0 | D3: 1 | D4: 1", - 11136 : "Power control module D1: 1 | D2:0 | D3: 1 | D4: 1", - 11137 : "Power control module D1: 0 | D2:1 | D3: 1 | D4: 1", - 11138 : "Power control module D1: 1 | D2:1 | D3: 1 | D4: 1", - 11139 : "Power control module release time", - 11140 : "Power control module release value", - 11141 : "Power control module fault tolerance time", - 11142 : "Oper.st.vol.maint.at Q on Dem., st.vol.maint.conf.", - 11143 : "Reactive power setpoint in var at Q on demand", - 11144 : "Reactive power setup as a % at Q on demand", - 11145 : "Grad.K react.curr.stat.for UV for dyn.grid support", - 11146 : "Grad.K reac.curr.stat.for dyn.grid support OV", - 11147 : "Char. curve number, conf. of the react.power mode", - 11148 : "Act.of char.curve,conf.of react.pow.char.curve mo.", - 11149 : "Act.threshold,conf.of react.power char. curve mode", - 11150 : "Deact.threshold,conf.of react.power char.curve mo.", - 11151 : "Threshold ref.,conf.of react.power char.line mode", - 11152 : "X values charact. curve 1", - 11153 : "Y values charact. curve 1", - 11154 : "X values charact. curve 2", - 11155 : "Y values charact. curve 2", - 11156 : "X values charact. curve 3", - 11157 : "Y values charact. curve 3", - 16777213 : "Information not available", - } - diff --git a/Docker/src/python/tHome/sma/test/FakeSocket.py b/Docker/src/python/tHome/sma/test/FakeSocket.py deleted file mode 100644 index 3a3e567..0000000 --- a/Docker/src/python/tHome/sma/test/FakeSocket.py +++ /dev/null @@ -1,16 +0,0 @@ - -class FakeSocket: - def __init__( self, reply ): - self.sent = None - self.reply = reply - self.closed = False - - def send( self, bytes ): - self.sent = bytes - - def recv( self, bufLen ): - return self.reply - - def close( self ): - self.closed = True - diff --git a/Docker/src/python/tHome/sma/test/acMaxPower.py b/Docker/src/python/tHome/sma/test/acMaxPower.py deleted file mode 100644 index 9a59695..0000000 --- a/Docker/src/python/tHome/sma/test/acMaxPower.py +++ /dev/null @@ -1,51 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestAcMaxPower ( T.util.test.Case ) : - def test_acMaxPower( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 7A 00 10 60 65 1E 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -0B 80 01 02 00 51 01 00 00 00 -03 00 00 00 01 1E 41 00 82 22 -AF 53 88 13 00 00 88 13 00 00 -88 13 00 00 88 13 00 00 01 00 -00 00 01 1F 41 00 82 22 AF 53 -88 13 00 00 88 13 00 00 00 00 -00 00 88 13 00 00 00 00 00 00 -01 20 41 00 82 22 AF 53 88 13 -00 00 88 13 00 00 00 00 00 00 -88 13 00 00 00 00 00 00 00 00 -00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.acMaxPower() - - l.decode = False - buf, decoder = l.acMaxPower() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - acMaxPower1 = 5000.0, - acMaxPower2 = 5000.0, - acMaxPower3 = 5000.0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/acPower.py b/Docker/src/python/tHome/sma/test/acPower.py deleted file mode 100644 index 9963210..0000000 --- a/Docker/src/python/tHome/sma/test/acPower.py +++ /dev/null @@ -1,51 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestAcPower ( T.util.test.Case ) : - def test_acPower( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 7A 00 10 60 65 1E 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -10 80 01 02 00 51 07 00 00 00 -09 00 00 00 01 40 46 40 86 22 -AF 53 B5 07 00 00 B5 07 00 00 -B5 07 00 00 B5 07 00 00 01 00 -00 00 01 41 46 40 86 22 AF 53 -B5 07 00 00 B5 07 00 00 B5 07 -00 00 B5 07 00 00 01 00 00 00 -01 42 46 40 86 22 AF 53 00 00 -00 80 00 00 00 80 00 00 00 80 -00 00 00 80 01 00 00 00 00 00 -00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.acPower() - - l.decode = False - buf, decoder = l.acPower() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - acPower1 = 1973.0, - acPower2 = 1973.0, - acPower3 = 0.0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/acTotalEnergy.py b/Docker/src/python/tHome/sma/test/acTotalEnergy.py deleted file mode 100644 index 091a4c5..0000000 --- a/Docker/src/python/tHome/sma/test/acTotalEnergy.py +++ /dev/null @@ -1,44 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestAcTotalEnergy ( T.util.test.Case ) : - def test_acTotalEnergy( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 46 00 10 60 65 11 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -0C 80 01 02 00 54 00 00 00 00 -01 00 00 00 01 01 26 00 85 22 -AF 53 D0 6A 09 00 00 00 00 00 -01 22 26 00 82 22 AF 53 2F 3B -00 00 00 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.acTotalEnergy() - - l.decode = False - buf, decoder = l.acTotalEnergy() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - totalEnergy = 617168.0, - dailyEnergy = 15151.0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/acTotalPower.py b/Docker/src/python/tHome/sma/test/acTotalPower.py deleted file mode 100644 index 592a4ea..0000000 --- a/Docker/src/python/tHome/sma/test/acTotalPower.py +++ /dev/null @@ -1,43 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestAcTotalPower ( T.util.test.Case ) : - def test_acTotalPower( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 42 00 10 60 65 10 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -12 80 01 02 00 51 00 00 00 00 -00 00 00 00 01 3F 26 40 86 22 -AF 53 6A 0F 00 00 6A 0F 00 00 -6A 0F 00 00 6A 0F 00 00 01 00 -00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.acTotalPower() - - l.decode = False - buf, decoder = l.acTotalPower() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - acPower = 3946.0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/acVoltage.py b/Docker/src/python/tHome/sma/test/acVoltage.py deleted file mode 100644 index 0b9fa75..0000000 --- a/Docker/src/python/tHome/sma/test/acVoltage.py +++ /dev/null @@ -1,73 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestAcVoltage ( T.util.test.Case ) : - def test_acVoltage( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 01 22 00 10 60 65 48 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -11 80 01 02 00 51 0A 00 00 00 -12 00 00 00 01 48 46 00 86 22 -AF 53 A6 2F 00 00 A6 2F 00 00 -A6 2F 00 00 A6 2F 00 00 01 00 -00 00 01 49 46 00 86 22 AF 53 -9B 2F 00 00 9B 2F 00 00 9B 2F -00 00 9B 2F 00 00 01 00 00 00 -01 4A 46 00 86 22 AF 53 FF FF -FF FF FF FF FF FF FF FF FF FF -FF FF FF FF 01 00 00 00 01 4B -46 00 86 22 AF 53 43 5F 00 00 -43 5F 00 00 43 5F 00 00 43 5F -00 00 01 00 00 00 01 4C 46 00 -86 22 AF 53 FF FF FF FF FF FF -FF FF FF FF FF FF FF FF FF FF -01 00 00 00 01 4D 46 00 86 22 -AF 53 FF FF FF FF FF FF FF FF -FF FF FF FF FF FF FF FF 01 00 -00 00 01 50 46 00 86 22 AF 53 -35 3F 00 00 35 3F 00 00 35 3F -00 00 35 3F 00 00 01 00 00 00 -01 51 46 00 86 22 AF 53 35 3F -00 00 35 3F 00 00 35 3F 00 00 -35 3F 00 00 01 00 00 00 01 52 -46 00 86 22 AF 53 FF FF FF FF -FF FF FF FF FF FF FF FF FF FF -FF FF 01 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.acVoltage() - - l.decode = False - buf, decoder = l.acVoltage() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - acVoltage1 = 121.98, - acVoltage2 = 121.87, - acVoltage3 = 0, - acGridVoltage = 243.87, - unknown1 = 0, - unknown2 = 0, - acCurrent1 = 16.181, - acCurrent2 = 16.181, - acCurrent3 = 0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/dcPower.py b/Docker/src/python/tHome/sma/test/dcPower.py deleted file mode 100644 index 9225256..0000000 --- a/Docker/src/python/tHome/sma/test/dcPower.py +++ /dev/null @@ -1,47 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestDcPower ( T.util.test.Case ) : - def test_dcPower( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 5E 00 10 60 65 17 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -0E 80 01 02 80 53 00 00 00 00 -01 00 00 00 01 1E 25 40 85 22 -AF 53 13 08 00 00 13 08 00 00 -13 08 00 00 13 08 00 00 01 00 -00 00 02 1E 25 40 85 22 AF 53 -21 08 00 00 21 08 00 00 21 08 -00 00 21 08 00 00 01 00 00 00 -00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.dcPower() - - l.decode = False - buf, decoder = l.dcPower() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - dcPower1 = 2067.0, - dcPower2 = 2081.0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/dcVoltage.py b/Docker/src/python/tHome/sma/test/dcVoltage.py deleted file mode 100644 index 3d0640a..0000000 --- a/Docker/src/python/tHome/sma/test/dcVoltage.py +++ /dev/null @@ -1,54 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestDcVoltage ( T.util.test.Case ) : - def test_dcVoltage( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 96 00 10 60 65 25 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -0F 80 01 02 80 53 02 00 00 00 -05 00 00 00 01 1F 45 40 85 22 -AF 53 B1 5E 00 00 B1 5E 00 00 -B1 5E 00 00 B1 5E 00 00 01 00 -00 00 02 1F 45 40 85 22 AF 53 -D5 5E 00 00 D5 5E 00 00 D5 5E -00 00 D5 5E 00 00 01 00 00 00 -01 21 45 40 85 22 AF 53 51 21 -00 00 51 21 00 00 51 21 00 00 -51 21 00 00 01 00 00 00 02 21 -45 40 85 22 AF 53 7D 21 00 00 -7D 21 00 00 7D 21 00 00 7D 21 -00 00 01 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.dcVoltage() - - l.decode = False - buf, decoder = l.dcVoltage() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - dcVoltage1 = 242.41, - dcVoltage2 = 242.77, - dcCurrent1 = 8.529, - dcCurrent2 = 8.573, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/gridFrequency.py b/Docker/src/python/tHome/sma/test/gridFrequency.py deleted file mode 100644 index 575d994..0000000 --- a/Docker/src/python/tHome/sma/test/gridFrequency.py +++ /dev/null @@ -1,43 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestGridFrequency ( T.util.test.Case ) : - def test_gridFrequency( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 42 00 10 60 65 10 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -13 80 01 02 00 51 13 00 00 00 -13 00 00 00 01 57 46 00 86 22 -AF 53 6C 17 00 00 6C 17 00 00 -6C 17 00 00 6C 17 00 00 01 00 -00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.gridFrequency() - - l.decode = False - buf, decoder = l.gridFrequency() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - frequency = 59.96, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/gridRelayStatus.py b/Docker/src/python/tHome/sma/test/gridRelayStatus.py deleted file mode 100644 index 57de820..0000000 --- a/Docker/src/python/tHome/sma/test/gridRelayStatus.py +++ /dev/null @@ -1,44 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestGridRelayStatus ( T.util.test.Case ) : - def test_GridRelayStatus( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 4E 00 10 60 65 13 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -0A 80 01 02 80 51 06 00 00 00 -06 00 00 00 01 64 41 08 85 22 -AF 53 33 00 00 01 37 01 00 00 -FD FF FF 00 FE FF FF 00 00 00 -00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.gridRelayStatus() - - l.decode = False - buf, decoder = l.gridRelayStatus() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - gridStatus = 'Closed', - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/info.py b/Docker/src/python/tHome/sma/test/info.py deleted file mode 100644 index 5849753..0000000 --- a/Docker/src/python/tHome/sma/test/info.py +++ /dev/null @@ -1,58 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestInfo ( T.util.test.Case ) : - def test_info( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 C6 00 10 60 65 31 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -05 80 01 02 00 58 00 00 00 00 -03 00 00 00 01 1E 82 10 82 19 -AF 53 53 4E 3A 20 31 39 31 33 -30 30 36 30 34 38 00 00 10 00 -00 00 10 00 00 00 00 00 00 00 -00 00 00 00 01 1F 82 08 82 19 -AF 53 41 1F 00 01 42 1F 00 00 -FE FF FF 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 -00 00 00 00 01 20 82 08 82 19 -AF 53 EE 23 00 00 EF 23 00 00 -F0 23 00 00 F1 23 00 01 F2 23 -00 00 F3 23 00 00 F4 23 00 00 -F5 23 00 00 01 20 82 08 82 19 -AF 53 FE FF FF 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False, raw=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.info() - - l.decode = False - buf, decoder = l.info() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - name = 'SN: 1913006048', - model = 'SB 5000TLUS-22', - type = 'Solar Inverter', - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/operationTime.py b/Docker/src/python/tHome/sma/test/operationTime.py deleted file mode 100644 index a994a9f..0000000 --- a/Docker/src/python/tHome/sma/test/operationTime.py +++ /dev/null @@ -1,44 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestOperationTime ( T.util.test.Case ) : - def test_OperationTime( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 46 00 10 60 65 11 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -0D 80 01 02 00 54 03 00 00 00 -04 00 00 00 01 2E 46 00 85 22 -AF 53 00 FA 0E 00 00 00 00 00 -01 2F 46 00 85 22 AF 53 42 97 -0E 00 00 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.operationTime() - - l.decode = False - buf, decoder = l.operationTime() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - operationTime = 981504.0, - feedTime = 956226.0, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/real/energy.py b/Docker/src/python/tHome/sma/test/real/energy.py deleted file mode 100755 index a83e7ad..0000000 --- a/Docker/src/python/tHome/sma/test/real/energy.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python - -import tHome as T - -#T.util.log.get( 'sma', 10, 'stdout' ) - -r = T.sma.report.energy( ip="192.168.1.14" ) -print "==================" -print r diff --git a/Docker/src/python/tHome/sma/test/real/full.py b/Docker/src/python/tHome/sma/test/real/full.py deleted file mode 100755 index 8d15b56..0000000 --- a/Docker/src/python/tHome/sma/test/real/full.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python - -import tHome as T - -#T.util.log.get( 'sma', 10, 'stdout' ) - -r = T.sma.report.full( ip="192.168.1.14" ) -print "==================" -print r diff --git a/Docker/src/python/tHome/sma/test/real/power.py b/Docker/src/python/tHome/sma/test/real/power.py deleted file mode 100755 index 34fe17b..0000000 --- a/Docker/src/python/tHome/sma/test/real/power.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python - -import tHome as T - -#T.util.log.get( 'sma', 10, 'stdout' ) - -r = T.sma.report.power( ip="192.168.1.14" ) -print "==================" -print r diff --git a/Docker/src/python/tHome/sma/test/status.py b/Docker/src/python/tHome/sma/test/status.py deleted file mode 100644 index 3562d6b..0000000 --- a/Docker/src/python/tHome/sma/test/status.py +++ /dev/null @@ -1,44 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestStatus ( T.util.test.Case ) : - def test_status( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 4E 00 10 60 65 13 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -08 80 01 02 80 51 00 00 00 00 -00 00 00 00 01 48 21 08 82 22 -AF 53 23 00 00 00 2F 01 00 00 -33 01 00 01 C7 01 00 00 FE FF -FF 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.status() - - l.decode = False - buf, decoder = l.status() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - status = 'Ok', - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/temp.py b/Docker/src/python/tHome/sma/test/temp.py deleted file mode 100644 index 2273805..0000000 --- a/Docker/src/python/tHome/sma/test/temp.py +++ /dev/null @@ -1,43 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestTemp ( T.util.test.Case ) : - def test_temp( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 42 00 10 60 65 10 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -09 80 01 02 00 52 00 00 00 00 -00 00 00 00 01 77 23 40 44 22 -AF 53 AC 1B 00 00 B6 1B 00 00 -B2 1B 00 00 B2 1B 00 00 01 00 -00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.temperature() - - l.decode = False - buf, decoder = l.temperature() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - temperature = 70.84, - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/sma/test/version.py b/Docker/src/python/tHome/sma/test/version.py deleted file mode 100644 index d8828bc..0000000 --- a/Docker/src/python/tHome/sma/test/version.py +++ /dev/null @@ -1,44 +0,0 @@ -import unittest -from FakeSocket import FakeSocket -import tHome as T - -#=========================================================================== - -#=========================================================================== -class TestVersion ( T.util.test.Case ) : - def test_version( self ): - reply = """ -53 4D 41 00 00 04 02 A0 00 00 -00 01 00 4E 00 10 60 65 13 90 -7D 00 AB 94 40 3B 00 A0 F7 00 -E0 27 06 72 00 00 00 00 00 00 -04 80 01 02 00 58 07 00 00 00 -07 00 00 00 01 34 82 00 94 19 -AF 53 00 00 00 00 00 00 00 00 -FE FF FF FF FE FF FF FF 04 06 -60 02 04 06 60 02 00 00 00 00 -00 00 00 00 00 00 00 00 -""" - l = T.sma.Link( "fake", connect=False ) - try: - l.socket = FakeSocket( T.util.hex.toBytes( reply ) ) - o1 = l.version() - - l.decode = False - buf, decoder = l.version() - o2 = decoder( buf ) - finally: - l.socket = None - - right = T.util.Data( - version = '02.60.06.R', - ) - - print o1 - - for k in right.keys(): - r = right[k] - self.eq( getattr( o1, k ), r, k ) - self.eq( getattr( o2, k ), r, k ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/thermostat/Thermostat.py b/Docker/src/python/tHome/thermostat/Thermostat.py deleted file mode 100644 index 85efa17..0000000 --- a/Docker/src/python/tHome/thermostat/Thermostat.py +++ /dev/null @@ -1,149 +0,0 @@ -#=========================================================================== -# -# Thermostat class -# -#=========================================================================== - -import json -import requests -import time -from .. import util - -#=========================================================================== -class Thermostat: - # Temperature mode - tmode = { 0 : "off", 1 : "heat", 2 : "cool", 3 : "auto" } - # Active heating/cooling flag. - tstate = { 0 : "off", 1 : "heat", 2 : "cool" } - - # Fan mode - fmode = { 0 : "auto", 1 : "circulate", 2 : "on" } - # Fan on/off flag. - fstate = { 0 : "off", 1 : "on" } - - #------------------------------------------------------------------------ - def __init__( self, label, host, mqttTempTopic, mqttModeTopic, - mqttStateTopic, mqttSetTopic ): - self.label = label - self.host = host - self.mqttTempTopic = mqttTempTopic - self.mqttModeTopic = mqttModeTopic - self.mqttStateTopic = mqttStateTopic - self.mqttSetTopic = mqttSetTopic - - self._log = util.log.get( "thermostat" ) - self._lastStatus = None - - - #------------------------------------------------------------------------ - def status( self ): - self._log.info( "%s:%s Getting status" % ( self.host, self.label ) ) - - url = "http://%s/tstat" % self.host - r = requests.get( url ) - - self._log.info( "%s:%s Received status %s" % ( self.host, self.label, - r.status_code ) ) - if r.status_code != requests.codes.ok: - self._lastStatus = None - e = util.Error( r.text ) - e.add( "Error requesting status from the thermostat '%s' at %s" % - ( self.label, self.host ) ) - raise e - - d = r.json() - - tempControl = 'auto' - if d["override"]: - tempControl = 'override' - elif d['hold']: - tempControl = 'hold' - - m = util.Data( - # Unix time. - time = time.time(), - # Current temperature at thermostat. - temperature = d["temp"], - # Thermostat mode (off, heating, cooling - tempMode = self.tmode[ d["tmode" ] ], - # Is the hvac currently running? - tempState = self.tstate[ d["tstate" ] ], - # Fan mode (auto, on) - fanMode = self.fmode[ d["fmode" ] ], - # Is the fan current on? - fanState = self.fstate[ d["fstate" ] ], - # program or override mode - tempControl = tempControl, - ) - - if "t_heat" in d: - m.target = d["t_heat"] - else: - m.target = d["t_cool"] - - self._log.info( "%s:%s Received: %s" % ( self.host, self.label, m ) ) - - self._lastStatus = m - return m - - #------------------------------------------------------------------------ - def messages( self, data=None ): - data = data if data is not None else self._lastStatus - if not data: - return [] - - s = self._lastStatus - msgs = [ - # tuple of ( topic, message ) - ( self.mqttTempTopic, { - 'time' : s.time, - 'temp' : s.temperature, - } ), - ( self.mqttModeTopic, { - 'time' : s.time, - 'sys' : s.tempMode, - 'fan' : s.fanMode, - 'temp' : s.tempControl, - } ), - ( self.mqttStateTopic, { - 'time' : s.time, - 'active' : s.tempState, - 'fan' : s.fanState, - 'target' : s.target, - 'temp' : s.temperature, - } ), - ] - - return msgs - - #------------------------------------------------------------------------ - def processSet( self, client, msg ): - data = json.loads( msg.payload ) - replyTopic = msg.topic + "/" + data['id'] - - status = None - if '/temp' in msg.topic: - value = data['temp'] - # TODO: set temperature - status = 0 - msg = "" - elif '/mode' in msg.topic: - sysMode = data['sys'] # off/heat/cool/auto - fanMode = data['fan'] # on/auto - # TODO: set mode - status = 0 - msg = "" - - if status is not None: - reply = { time : time.time(), error : status, msg : msg } - payload = json.dumps( reply ) - client.publish( replyTopic, payload ) - - #------------------------------------------------------------------------ - def __str__( self ): - return """Thermostat( - Label = '%s', - Host = '%s', - )""" % ( self.label, self.host ) - - #------------------------------------------------------------------------ diff --git a/Docker/src/python/tHome/thermostat/__init__.py b/Docker/src/python/tHome/thermostat/__init__.py deleted file mode 100644 index 84ccbae..0000000 --- a/Docker/src/python/tHome/thermostat/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -#=========================================================================== -# -# Radio thermostat module. -# -#=========================================================================== - -__doc__ = """Radio Thermostat package. - - -Used for reading radio-thermostat brand WIFI thermostats. -Logging object name: tHome.thermostat -""" - -#=========================================================================== - - -#=========================================================================== - -from . import config -from .Thermostat import Thermostat - -#=========================================================================== diff --git a/Docker/src/python/tHome/thermostat/config.py b/Docker/src/python/tHome/thermostat/config.py deleted file mode 100644 index 9838aca..0000000 --- a/Docker/src/python/tHome/thermostat/config.py +++ /dev/null @@ -1,64 +0,0 @@ -#=========================================================================== -# -# Config file -# -#=========================================================================== - -__doc__ = """Config file parsing. -""" - -from .. import util -from ..util import config as C -from .Thermostat import Thermostat - -#=========================================================================== - -# Config file section name and defaults. -configEntries = [ - # ( name, converter function, default value ) - C.Entry( "logFile", util.path.expand ), - C.Entry( "logLevel", int, 20 ), # INFO - C.Entry( "thermostats", list ), - ] - -thermostatEntries = [ - # ( name, converter function, default value ) - C.Entry( "host", str ), - C.Entry( "label", str ), - C.Entry( "mqttTempTopic", str ), - C.Entry( "mqttModeTopic", str ), - C.Entry( "mqttStateTopic", str ), - C.Entry( "mqttSetTopic", str ), - ] - -#=========================================================================== -def parse( configDir, configFile='thermostat.py' ): - m = C.readAndCheck( configDir, configFile, configEntries ) - - # Replace the thermostat dict inputs with Thermostat objecdts. - m.thermostats = parseThermostats( m.thermostats ) - - return m - -#=========================================================================== -def parseThermostats( entries ): - assert( len( entries ) > 0 ) - - thermostats = [] - for e in entries: - C.check( e, thermostatEntries ) - thermostats.append( Thermostat( **e ) ) - - return thermostats - -#=========================================================================== -def log( config, logFile=None ): - if not logFile: - logFile = config.logFile - - return util.log.get( "thermostat", config.logLevel, logFile ) - -#=========================================================================== - - - diff --git a/Docker/src/python/tHome/weatherUnderground/__init__.py b/Docker/src/python/tHome/weatherUnderground/__init__.py deleted file mode 100644 index dd85bb5..0000000 --- a/Docker/src/python/tHome/weatherUnderground/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -#=========================================================================== -# -# Weather Underground web site access -# -#=========================================================================== - -__doc__ = """Communicate with the Weather Underground web site. - -Allows upload of weather data to a personal weather station. - -""" - -#=========================================================================== - -from . import cmdLine -from . import config -from . import start - -#=========================================================================== diff --git a/Docker/src/python/tHome/weatherUnderground/cmdLine.py b/Docker/src/python/tHome/weatherUnderground/cmdLine.py deleted file mode 100644 index 23596ff..0000000 --- a/Docker/src/python/tHome/weatherUnderground/cmdLine.py +++ /dev/null @@ -1,52 +0,0 @@ -#=========================================================================== -# -# Command line processing -# -#=========================================================================== - -import argparse -import numpy as np -from .. import broker -from . import config -from . import start - -#=========================================================================== - -def run( args ): - """Parse command line arguments to upload weather data. - - = INPUTS - - args [str]: List of command line arguments. [0] should be the - program name. - """ - p = argparse.ArgumentParser( prog=args[0], - description="SMA inverter reader" ) - p.add_argument( "-c", "--configDir", metavar="configDir", - default="/var/config/tHome", - help="T-Home configuration directory." ) - p.add_argument( "-l", "--log", metavar="logFile", - default=None, help="Logging file to use. Input 'stdout' " - "to log to the screen." ) - p.add_argument( "--debug", default=False, action="store_true", - help="Debugging - no sending, just print" ) - c = p.parse_args( args[1:] ) - - if c.debug: - c.log = "stdout" - - # Parse the sma and broker config files. - cfg = config.parse( c.configDir ) - log = config.log( cfg, c.log ) - - if c.debug: - log.setLevel( 10 ) - - # Create the MQTT client and connect it to the broker. - client = broker.connect( c.configDir, log ) - - # Numpy reports invalid errors when dealing w/ nans which don't - # matter to this algorithm. - with np.errstate( invalid='ignore' ): - start.start( cfg, client, debug=c.debug ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/weatherUnderground/config.py b/Docker/src/python/tHome/weatherUnderground/config.py deleted file mode 100644 index fca5979..0000000 --- a/Docker/src/python/tHome/weatherUnderground/config.py +++ /dev/null @@ -1,47 +0,0 @@ -#=========================================================================== -# -# Config file -# -#=========================================================================== - -__doc__ = """Config file parsing. -""" - -from .. import util -from ..util import config as C - -#=========================================================================== - -# Config file section name and defaults. -configEntries = [ - # ( name, converter function, default value ) - C.Entry( "uploadUrl", str ), - C.Entry( "id", str ), - C.Entry( "password", str ), - C.Entry( "poll", int, 120 ), - C.Entry( "maxRate", int, 10 ), - C.Entry( "digits", int, 2 ), - C.Entry( "mqttWind", str, None ), - C.Entry( "mqttTemp", list, [] ), - C.Entry( "mqttRain", str, None ), - C.Entry( "mqttBarometer", str, None ), - C.Entry( "mqttHumidity", str, None ), - C.Entry( "logFile", util.path.expand ), - C.Entry( "logLevel", int, 20 ), # INFO - ] - -#=========================================================================== -def parse( configDir, configFile='weatherUnderground.py' ): - return C.readAndCheck( configDir, configFile, configEntries ) - -#=========================================================================== -def log( config, logFile=None ): - if not logFile: - logFile = config.logFile - - return util.log.get( "weatherUnderground", config.logLevel, logFile ) - -#=========================================================================== - - - diff --git a/Docker/src/python/tHome/weatherUnderground/start.py b/Docker/src/python/tHome/weatherUnderground/start.py deleted file mode 100644 index 73a67df..0000000 --- a/Docker/src/python/tHome/weatherUnderground/start.py +++ /dev/null @@ -1,403 +0,0 @@ -#=========================================================================== -# -# Main report processing -# -#=========================================================================== - -import logging -import requests -import datetime -import threading -import numpy as np -import time -from StringIO import StringIO -from .. import util - -#=========================================================================== -class CircularTimeBuf: - """Circular buffer class. - - This stores data in a numpy array as a circular buffer that covers - a set amount of time. When data is added (with a time tag), it - will automatically erase any data older than the input time length. - This allows for fast and easy computations involving the last n - seconds of data regardless of the rate that data is seen. - """ - def __init__( self, timeLen, maxRate, label=None, log=None ): - self.label = label if label is not None else "" - self.log = log - - numEntries = int( timeLen / maxRate ) - - self._dt = timeLen - self._len = numEntries - - # Index of the last entry added to the buffer. -1 is used to - # indicate that no data is present. - self._lastIdx = -1 - - # Create an array of NaN values. v[0] is the array of times, - # v[1] is the array of values. - self.v = np.full( ( 2, self._len ), np.nan ) - - #-------------------------------------------------------------------------- - def __nonzero__( self ): - return self._lastIdx != -1 - - #-------------------------------------------------------------------------- - def append( self, t, v ): - # Remove any data older than t-self._dt - self.updateTo( t ) - - idx = self._nextIdx( self._lastIdx ) - - self.v[0][idx] = t - self.v[1][idx] = v - - self._lastIdx = idx - - # Debugging output - if self.log and self.log.isEnabledFor( logging.DEBUG ): - s = StringIO() - print >> s, "%s record time: %.1f\n" % ( self.label, t ) - if self._lastIdx != -1: - i = self._lastIdx - while not np.isnan( self.v[0][i] ): - print >> s, " %.1f %.1f " % ( self.v[0][i], self.v[1][i] ) - i = self._prevIdx( i ) - - self.log.debug( s.getvalue().strip() ) - - #-------------------------------------------------------------------------- - def mean( self, t=None ): - # Remove any data older than t-self._dt - if t: - self.updateTo( t ) - - # No data in the buffer. - if self._lastIdx == -1: - return None - - # Compute the mean value and ignore any nans. - return np.nanmean( self.v[1] ) - - #-------------------------------------------------------------------------- - def sum( self, t=None ): - # Remove any data older than t-self._dt - if t: - self.updateTo( t ) - - # No data in the buffer. - if self._lastIdx == -1: - return None - - # Sum all the values and ignore any nans. - return np.nansum( self.v[1] ) - - #-------------------------------------------------------------------------- - def max( self, t=None ): - # Remove any data older than t-self._dt - if t: - self.updateTo( t ) - - # No data in the buffer. - if self._lastIdx == -1: - return None - - # Compute the max value and ignore any nans. - return np.nanmax( self.v[1] ) - - #-------------------------------------------------------------------------- - def min( self, t=None ): - # Remove any data older than t-self._dt - if t: - self.updateTo( t ) - - # No data in the buffer. - if self._lastIdx == -1: - return None - - # Compute the max value and ignore any nans. - return np.nanmin( self.v[1] ) - - #-------------------------------------------------------------------------- - def updateTo( self, time ): - if self._lastIdx == -1: - return - - # Delete any entries that are more than self._dt before the - # input time. - tBeg = time - self._dt - - # Find the indeces where the time is too old. This returns a - # tuple of len 1 so it can be used as an array index below. - i = np.where( self.v[0] < tBeg ) - - # Reset those values to nan - if i: - # Get an index of the current nan values. - nans = np.where( np.isnan( self.v[0] ) == True ) - - self.v[0][i] = np.nan - self.v[1][i] = np.nan - - # If the number of existing nan values and old values is the - # length of the array, reset lastIdx to indicate there is no - # data. This eliminates warnings about all-nan axis when - # doing computations. - if ( len( nans[0] ) + len( i[0] ) ) == self._len: - self._lastIdx = -1 - - #-------------------------------------------------------------------------- - def _nextIdx( self, index ): - nextIdx = index + 1 - if nextIdx == self._len: - nextIdx = 0 - - return nextIdx - - #-------------------------------------------------------------------------- - def _prevIdx( self, index ): - prevIdx = index - 1 - if prevIdx < 0: - prevIdx = self._len - 1 - - return prevIdx - - #-------------------------------------------------------------------------- - -#=========================================================================== -class Reader: - def __init__( self, config, log ): - self.config = config - self.log = log - - # Fields that use config.poll are used to return the average - # value over the poll interval. That decouples the interval we - # get messages in and the upload reporting interval. Some - # fields have fixed intervals that weather underground requires - # (like rain). - self.temps = [] - self.tempKeys = [] - for i in range( len( config.mqttTemp ) ): - self.temps.append( CircularTimeBuf( config.poll, config.maxRate, - "Temp %d" % i, self.log ) ) - if i == 0: - self.tempKeys.append( 'tempf' ) - else: - self.tempKeys.append( 'temp%df' % i ) - - self.humidity = CircularTimeBuf( config.poll, config.maxRate, - "Humidity", self.log ) - self.barometer = CircularTimeBuf( config.poll, config.maxRate, - "Barometer", self.log ) - - # Uploaded wind speed/dir are the average over the poll interval - # Gust values will be the maximum value over the poll interval. - self.windSpeed = CircularTimeBuf( config.poll, config.maxRate, - "Wind Speed", self.log ) - - # Average direction has to be computed by averaging the vector - # directions and then turning that back to an angle. See: - # http://www.webmet.com/met_monitoring/622.html - # A weighted version is shown here - but I'm not doing that - # because the speed and direction messages are separate - so - # this is just the averaged direction. - # east = speed * sin( dir ) - # north = speed * cos( dir ) - # ve = -1/n sum( east ) - # vn = -1/n sum( north ) - # Average dir = arctan( ve/vn ) +/- 180 - self.windEast = CircularTimeBuf( config.poll, config.maxRate, - "Wind Dir East", self.log ) - self.windNorth = CircularTimeBuf( config.poll, config.maxRate, - "Wind Dir North", self.log ) - - # Accumulate rain for the day. Store the current date when the - # first reading shows up. If the date changes, then we reset - # the accumulation. - self.rainDate = None - self.rainDayTotal = 0.0 - - # Accumulate rain for the last hour and allow at least 15 - # seconds between messages (acurite publishes every 36 seconds - # so this is fine). - self.rainHour = CircularTimeBuf( 3600.0, 15, "Rain Hour", self.log ) - - # MQTT will be pushing data to use and we'll be publishing it - # out so we need to lock when accessing the numpy matrix. - self.lock = threading.Lock() - - #-------------------------------------------------------------------------- - def readMsg( self, client, userData, msg ): - with self.lock: - topic = msg.topic - data = util.json.loads( msg.payload ) - self.log.info( "Read %s: %s" % ( topic, data ) ) - - time = data['time'] - - for i in range( len( self.config.mqttTemp ) ): - if topic == self.config.mqttTemp[i]: - self.temps[i].append( time, data['temperature' ] ) - break - - else: - if topic == self.config.mqttHumidity: - self.humidity.append( time, data['humidity' ] ) - - elif topic == self.config.mqttBarometer: - self.barometer.append( time, data['pressure' ] ) - - elif topic == self.config.mqttRain: - today = datetime.date.today() - - # Reset the rain if the local day changes. - if self.rainDate != today: - self.rainDayTotal = 0.0 - self.rainDate = today - self.log.info( "Update rain date to %s" % today ) - - self.rainDayTotal += data['rain'] - self.rainHour.append( time, data['rain'] ) - - elif topic == self.config.mqttWindSpeed: - self.windSpeed.append( time, data['speed'] ) - - elif topic == self.config.mqttWindDir: - # Note: if we multiple the trig terms by the speed, it - # would give us a weighted direction. But that - # requires matching the direction msg time with the - # speed msg time and requires they both exist. So it's - # easier to just average the directions. - angle = np.deg2rad( data['direction'] ) - self.windEast.append( time, np.sin( angle ) ) - self.windNorth.append( time, np.cos( angle ) ) - - #-------------------------------------------------------------------------- - def updatePayload( self, payload ): - with self.lock: - t = time.time() - dt = datetime.datetime.utcnow() - payload['dateutc'] = dt.strftime( '%Y-%m-%d %H:%M:%S' ) - - # Only update the payload dictionary if the value from the - # circular buffer isn't None. That can happen if we don't - # have any data for the requested interval. Round the result - # to a few digits to keep the upload message smaller. - def updateDict( key, value, digits=self.config.digits ): - if value is not None: - payload[key] = round( value, digits ) - - haveData = False - - if self.windSpeed: - haveData = True - updateDict( 'windspeedmph', self.windSpeed.mean( t ) ) - updateDict( 'windgustmph', self.windSpeed.max( t ) ) - - if self.windEast: - # Average the wind direction using vector math. - # See: http://www.webmet.com/met_monitoring/622.html - avgEast = - self.windEast.mean( t ) - avgNorth = - self.windNorth.mean( t ) - windDir = np.rad2deg( np.arctan2( avgEast, avgNorth ) ) - # Shift to the correct quadrant - if windDir < 180: - windDir += 180 - else: - windDir -= 180 - - updateDict( 'winddir', windDir ) - - if self.humidity: - haveData = True - updateDict( 'humidity', self.humidity.mean( t ) ) - - if self.barometer: - haveData = True - updateDict( 'baromin', self.barometer.mean( t ) ) - - if self.rainDate is not None: - haveData = True - updateDict( 'dailyrainin', self.rainDayTotal, 3 ) - updateDict( 'rainin', self.rainHour.sum( t ), 3 ) - - for i in range( len( self.temps ) ): - if self.temps[i]: - haveData = True - updateDict( self.tempKeys[i], self.temps[i].mean( t ) ) - - return haveData - - #-------------------------------------------------------------------------- - -#=========================================================================== -def start( config, client, debug=False ): - fromts = datetime.datetime.fromtimestamp - - log = util.log.get( "weatherUnderground" ) - - # URL arguments to send. - payloadBase = { - 'action' : 'updateraw', - 'ID' : config.id, - 'PASSWORD' : config.password, - 'dateutc' : None, # 'YYYY-MM-DD HH:MM:SS' - # 'winddir' : 0-360 - # 'windspeedmph' : speed in mph - # 'windgustmph' : gust in mph - # 'humidity' : 0-100% - # 'tempf' : temperature F - # 'temp2f' : temperature F - # 'rainin' : inches of rain over the last hour - # 'dailyrainin' : inches of rain over the local day - # 'baromin' : barometric pressure in inches - } - payload = payloadBase.copy() - - # Create a reader to process weather mes sages. - reader = Reader( config, log ) - client.on_message = reader.readMsg - - # Subscribe to all the weather topics we need to upload. - for topic in config.mqttTemp: - client.subscribe( topic ) - - client.subscribe( config.mqttHumidity ) - client.subscribe( config.mqttBarometer ) - client.subscribe( config.mqttRain ) - client.subscribe( config.mqttWindSpeed ) - client.subscribe( config.mqttWindDir ) - - # Start the MQTT as a background thread. This way we can run our - # upload process in the rest of the code. - client.loop_start() - - while True: - # Fill in the current values into the payload dict. - haveData = reader.updatePayload( payload ) - if haveData: - try: - log.info( "Uploading: %s" % payload ) - - # Send the HTTP request. - r = requests.get( config.uploadUrl, params=payload ) - log.debug( "URL: %s" % r.url ) - - if r.text.strip() != "success": - log.error( "WUG response: '%s'" % r.text ) - - except: - log.exception( "Upload failed to run" ) - - # Clear the payload back to the minimum set of fields. - payload = payloadBase.copy() - - else: - log.info( "Ignoring send opportunity - no data" ) - - # Sleep until the next time we should upload. - time.sleep( config.poll ) - -#=========================================================================== diff --git a/Docker/src/python/tHome/weatherUnderground/test/buf.py b/Docker/src/python/tHome/weatherUnderground/test/buf.py deleted file mode 100644 index 7768939..0000000 --- a/Docker/src/python/tHome/weatherUnderground/test/buf.py +++ /dev/null @@ -1,71 +0,0 @@ -import numpy as np -import warnings -import tHome.weatherUnderground.start as S - -buf = S.CircularTimeBuf( 60, 10 ) - -print "=================" -print "Empty" -print "=================" -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) - -print "=================" -buf.append( 10, 1 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print - -buf.append( 20, 2 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print - -buf.append( 30, 3 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print - -buf.append( 40, 4 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print - -buf.append( 50, 5 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print - -buf.append( 60, 6 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print - -buf.append( 70, 7 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) -print -print "=================" - -buf.append( 120, 12 ) -print buf.v -print "Min/Max: %s / %s Avg: %s" % ( buf.min(), buf.max(), buf.mean() ) - -print "=================" -buf.append( 130, 13 ) -buf.append( 140, 14 ) -buf.append( 150, 15 ) -buf.append( 160, 16 ) -buf.append( 170, 17 ) -print buf.v -print -print "Update to t=200" -print "Min/Max: %s / %s Avg: %s" % ( buf.min(200), buf.max(200), buf.mean(200) ) -print buf.v - -print "=================" -print "Update to t=500" -buf.updateTo( 500 ) -print buf.v - -print "Min:",buf.min( 500 ) - diff --git a/Docker/src/systemd/tHome-acurite.service b/Docker/src/systemd/tHome-acurite.service deleted file mode 100644 index d52c1e4..0000000 --- a/Docker/src/systemd/tHome-acurite.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Acu-rite weather bridge reader -After=network.target - -[Service] -EnvironmentFile=/home/ted/proj/tHome/systemd/tHome.env -Type=simple -User=ted -ExecStart=/home/ted/proj/tHome/bin/tHome-acurite.py --log /var/log/tHome/acurite.log --configDir /home/ted/proj/tHome/conf - -[Install] -WantedBy=multi-user.target - - diff --git a/Docker/src/systemd/tHome-sma.service b/Docker/src/systemd/tHome-sma.service deleted file mode 100644 index bccfec4..0000000 --- a/Docker/src/systemd/tHome-sma.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=T-Home SMA solar inverter reader -After=network.target - -[Service] -EnvironmentFile=/home/ted/proj/tHome/systemd/tHome.env -Type=simple -User=ted -ExecStart=/home/ted/proj/tHome/bin/tHome-sma.py --log /var/log/tHome/sma.log --configDir /home/ted/proj/tHome/conf - -[Install] -WantedBy=multi-user.target diff --git a/Docker/src/systemd/tHome-thermostat.service b/Docker/src/systemd/tHome-thermostat.service deleted file mode 100644 index db085fd..0000000 --- a/Docker/src/systemd/tHome-thermostat.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=T-Home WIFI thermostat reader -After=network.target - -[Service] -EnvironmentFile=/home/ted/proj/tHome/systemd/tHome.env -Type=simple -User=ted -ExecStart=/home/ted/proj/tHome/bin/tHome-thermostat.py --log /var/log/tHome/thermostat.log --configDir /home/ted/proj/tHome/conf - -[Install] -WantedBy=multi-user.target - - - diff --git a/Docker/src/upstart/tHome-acurite.conf b/Docker/src/upstart/tHome-acurite.conf deleted file mode 100644 index 254cba6..0000000 --- a/Docker/src/upstart/tHome-acurite.conf +++ /dev/null @@ -1,16 +0,0 @@ -description "Acu-rite bridge reader" -author "Ted Drain" - -start on filesystem or runlevel [2345] -stop on shutdown - -env USER=ted -env CMD=/home/ted/proj/tHome/bin/tHome-acurite.py -env LOG=/var/log/tHome/acurite.log -env CONFIG=/home/ted/proj/tHome/conf - -script - exec start-stop-daemon --start -c $USER --exec $CMD -- $CONFIG $LOG -end script - - diff --git a/Docker/src/upstart/tHome-sma.conf b/Docker/src/upstart/tHome-sma.conf deleted file mode 100644 index 2a1f330..0000000 --- a/Docker/src/upstart/tHome-sma.conf +++ /dev/null @@ -1,16 +0,0 @@ -description "T-Home SMA solar inverter reader" -author "Ted Drain" - -start on filesystem or runlevel [2345] -stop on shutdown - -env USER=ted -env CMD=/home/ted/proj/tHome/bin/tHome-sma.py -env LOG=/var/log/tHome/sma.log -env CONFIG=/home/ted/proj/tHome/conf - -script - exec start-stop-daemon --start -c $USER --exec $CMD -- -l $LOG -c $CONFIG -end script - - diff --git a/Docker/src/upstart/tHome-thermostat.conf b/Docker/src/upstart/tHome-thermostat.conf deleted file mode 100644 index 542ce1e..0000000 --- a/Docker/src/upstart/tHome-thermostat.conf +++ /dev/null @@ -1,16 +0,0 @@ -description "T-Home WIFI thermostat reader" -author "Ted Drain" - -start on filesystem or runlevel [2345] -stop on shutdown - -env USER=ted -env CMD=/home/ted/proj/tHome/bin/tHome-thermostat.py -env LOG=/var/log/tHome/thermostat.log -env CONFIG=/home/ted/proj/tHome/conf - -script - exec start-stop-daemon --start -c $USER --exec $CMD -- -l $LOG -c $CONFIG -end script - - diff --git a/Docker/src/upstart/tHome-wug.conf b/Docker/src/upstart/tHome-wug.conf deleted file mode 100644 index c6987ee..0000000 --- a/Docker/src/upstart/tHome-wug.conf +++ /dev/null @@ -1,17 +0,0 @@ -description "T-Home Weather Underground uploader" -author "Ted Drain" - -start on filesystem or runlevel [2345] -stop on shutdown - -env USER=ted -env CMD=/home/ted/proj/tHome/bin/tHome-wug.py -env LOG=/var/log/tHome/weatherUnderground.log -env CONFIG=/home/ted/proj/tHome/conf -env PYTHONPATH=/home/ted/python - -script - exec start-stop-daemon --start -c $USER --exec $CMD -- -l $LOG -c $CONFIG -end script - -