Feature/v0.2.0 (#7)
* heateroutput limit 0 - 15000 w * heatoutput always positive * ENUM_IN_FSV_2041 value 0c00 unknwon added * recalculate crc6 checksum and check it * skip exception to reduce logging * NASAPacket and NASAMessage prepared for write mode MQTT Auto Discovery changed single entitity to all entities NASA Packet crc16 Checksum verificated * - Changed MQTT Auto Discovery Config Message from single Entitiy to all Entities at ones, known devices are fully configured, not known empty (markt to delete) - NASAPacket and NASAMessage are now bidirectional, can decode and encode Packets - Added crc16 Checksum check for any Packet to reduce incorrect value changes - Folling warnings moved to SkipInvalidPacketException and from warning to debug log level to reduce Logentries - Source Adress Class out of enum - Destination Adress Class out of enum - Checksum for package could not be validatet calculated - Message with structure type must have capacity of 1. * NASA_OUTDOOR_HP as kw unit * NASA Repository, measurements enums completed * filter wifikit heartbeat * process only packets from indoor or outdoor * correct readme * remove expire * device discovery status * new mqtt hass configuration approach * added new measurements * added new logging features from config * NASA_EHSSENTINEL_TOTAL_COP added * removed silentMode, added logging proccessedMessage * loaded devices * loaded devices counter fix * only if retain true * final 0.2.0 commit
This commit is contained in:
@@ -63,13 +63,6 @@ class IndentFormatter(logging.Formatter):
|
||||
del rec.indent; del rec.function
|
||||
return out
|
||||
|
||||
class MessageProcessorFilter(logging.Filter):
|
||||
def filter(self, record):
|
||||
# Suppress INFO level messages from MessageProcessor.py
|
||||
if record.levelno == logging.INFO and record.pathname.endswith("MessageProcessor.py"):
|
||||
return False
|
||||
return True
|
||||
|
||||
# The following code sets up a custom logger with indentation support.
|
||||
# It creates a custom formatter, a logger instance, and a stream handler.
|
||||
# The custom formatter is set to the handler, which is then added to the logger.
|
||||
@@ -91,15 +84,3 @@ def setDebugMode():
|
||||
"""
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.debug("Debug mode is on...")
|
||||
|
||||
def setSilent():
|
||||
"""
|
||||
Sets the logger to silent mode, where only messages at the ERROR level or higher are displayed.
|
||||
If the current logging level is not 'DEBUG', this function will log an informational message
|
||||
indicating that silent mode is being activated and then set the logging level to ERROR.
|
||||
"""
|
||||
if logger.level != logging.DEBUG:
|
||||
logger.info("Silent Mode is turning on, only Messages at Level WARNING or higher are displayed")
|
||||
#logger.setLevel(logging.ERROR)
|
||||
# Add the filter to suppress INFO level messages from MessageProcessor.py
|
||||
logger.addFilter(MessageProcessorFilter())
|
||||
30
EHSConfig.py
30
EHSConfig.py
@@ -26,6 +26,7 @@ class EHSConfig():
|
||||
GENERAL = None
|
||||
SERIAL = None
|
||||
NASA_REPO = None
|
||||
LOGGING = {}
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""
|
||||
@@ -77,6 +78,10 @@ class EHSConfig():
|
||||
self.MQTT = config.get('mqtt')
|
||||
self.GENERAL = config.get('general')
|
||||
self.SERIAL = config.get('serial')
|
||||
if 'logging' in config:
|
||||
self.LOGGING = config.get('logging')
|
||||
else:
|
||||
self.LOGGING = {}
|
||||
logger.debug(f"Configuration loaded: {config}")
|
||||
|
||||
self.validate()
|
||||
@@ -97,9 +102,6 @@ class EHSConfig():
|
||||
self.NASA_REPO = yaml.safe_load(file)
|
||||
else:
|
||||
raise ConfigException(argument=self.GENERAL['nasaRepositoryFile'], message="NASA Respository File is missing")
|
||||
|
||||
if 'silentMode' not in self.GENERAL:
|
||||
self.GENERAL['silentMode'] = True
|
||||
|
||||
if 'protocolFile' not in self.GENERAL:
|
||||
self.GENERAL['protocolFile'] = None
|
||||
@@ -132,4 +134,24 @@ class EHSConfig():
|
||||
raise ConfigException(argument=self.SERIAL['device'], message="mqtt user parameter is missing")
|
||||
|
||||
if 'password' not in self.MQTT and 'user' in self.MQTT:
|
||||
raise ConfigException(argument=self.SERIAL['device'], message="mqtt password parameter is missing")
|
||||
raise ConfigException(argument=self.SERIAL['device'], message="mqtt password parameter is missing")
|
||||
|
||||
if 'messageNotFound' not in self.LOGGING:
|
||||
self.LOGGING['messageNotFound'] = False
|
||||
|
||||
if 'messageNotFound' not in self.LOGGING:
|
||||
self.LOGGING['messageNotFound'] = False
|
||||
|
||||
if 'deviceAdded' not in self.LOGGING:
|
||||
self.LOGGING['deviceAdded'] = True
|
||||
|
||||
if 'packetNotFromIndoorOutdoor' not in self.LOGGING:
|
||||
self.LOGGING['packetNotFromIndoorOutdoor'] = False
|
||||
|
||||
if 'proccessedMessage' not in self.LOGGING:
|
||||
self.LOGGING['proccessedMessage'] = False
|
||||
|
||||
logger.info(f"Logging Config:")
|
||||
for key, value in self.LOGGING.items():
|
||||
logger.info(f" {key}: {value}")
|
||||
|
||||
@@ -46,8 +46,8 @@ class ArgumentException(EHSException):
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.argument} -> {self.message}'
|
||||
|
||||
class MessageCapacityStructureWarning(EHSException):
|
||||
|
||||
class SkipInvalidPacketException(EHSException):
|
||||
"""Exception raised for invalid message types.
|
||||
|
||||
Attributes:
|
||||
|
||||
374
MQTTClient.py
374
MQTTClient.py
@@ -13,25 +13,9 @@ from EHSConfig import EHSConfig
|
||||
|
||||
class MQTTClient:
|
||||
"""
|
||||
MQTTClient is a singleton class that manages the connection to an MQTT broker and handles
|
||||
publishing and subscribing to topics. It is designed to work with Home Assistant for
|
||||
auto-discovery of devices and sensors.
|
||||
|
||||
Attributes:
|
||||
_instance (MQTTClient): The single instance of the MQTTClient class.
|
||||
STOP (asyncio.Event): Event to signal stopping the MQTT client.
|
||||
DEVICE_ID (str): The device ID used for MQTT topics.
|
||||
config (EHSConfig): Configuration object for the MQTT client.
|
||||
args (EHSArguments): Arguments object for the MQTT client.
|
||||
broker (str): URL of the MQTT broker.
|
||||
port (int): Port of the MQTT broker.
|
||||
client_id (str): Client ID for the MQTT client.
|
||||
client (gmqtt.Client): MQTT client instance.
|
||||
topicPrefix (str): Prefix for MQTT topics.
|
||||
homeAssistantAutoDiscoverTopic (str): Topic for Home Assistant auto-discovery.
|
||||
useCamelCaseTopicNames (bool): Flag to use camel case for topic names.
|
||||
known_topics (list): List to keep track of known topics.
|
||||
known_devices_topic (str): Dedicated topic for storing known topics.
|
||||
MQTTClient is a singleton class that manages the connection and communication with an MQTT broker.
|
||||
It handles the initialization, connection, subscription, and message publishing for the MQTT client.
|
||||
The class also supports Home Assistant auto-discovery and maintains a list of known devices.
|
||||
"""
|
||||
_instance = None
|
||||
STOP = asyncio.Event()
|
||||
@@ -40,17 +24,16 @@ class MQTTClient:
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""
|
||||
Create a new instance of the MQTTClient class if one does not already exist.
|
||||
This method ensures that the MQTTClient class follows the Singleton design pattern,
|
||||
meaning only one instance of the class can exist at any given time. If an instance
|
||||
already exists, it returns the existing instance. Otherwise, it creates a new instance
|
||||
and sets the _initialized attribute to False.
|
||||
Create a new instance of the class if one does not already exist.
|
||||
This method ensures that only one instance of the class is created (singleton pattern).
|
||||
If an instance already exists, it returns the existing instance.
|
||||
Otherwise, it creates a new instance, marks it as uninitialized, and returns it.
|
||||
Args:
|
||||
cls (type): The class being instantiated.
|
||||
cls: The class being instantiated.
|
||||
*args: Variable length argument list.
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
Returns:
|
||||
MQTTClient: The single instance of the MQTTClient class.
|
||||
An instance of the class.
|
||||
"""
|
||||
|
||||
if not cls._instance:
|
||||
@@ -60,26 +43,25 @@ class MQTTClient:
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the MQTTClient instance.
|
||||
This constructor initializes the MQTT client with the configuration
|
||||
provided by the EHSConfig and EHSArguments classes. It sets up the
|
||||
MQTT broker connection details, client ID, and authentication credentials
|
||||
if provided. It also assigns callback functions for various MQTT events
|
||||
such as connect, disconnect, message, and subscribe. Additionally, it
|
||||
initializes the topic prefix, Home Assistant auto-discover topic, and
|
||||
topic naming convention.
|
||||
Initializes the MQTTClient instance.
|
||||
This constructor sets up the MQTT client with the necessary configuration
|
||||
parameters, including broker URL, port, client ID, and authentication credentials.
|
||||
It also assigns callback functions for various MQTT events such as connect,
|
||||
disconnect, message, and subscribe. Additionally, it initializes topic-related
|
||||
settings and a list to keep track of known topics.
|
||||
Attributes:
|
||||
config (EHSConfig): Configuration object for the MQTT client.
|
||||
args (EHSArguments): Argument parser object for the MQTT client.
|
||||
config (EHSConfig): Configuration object for MQTT settings.
|
||||
args (EHSArguments): Argument parser object.
|
||||
broker (str): URL of the MQTT broker.
|
||||
port (int): Port number of the MQTT broker.
|
||||
client_id (str): Client ID for the MQTT connection.
|
||||
client (gmqtt.Client): gmqtt client instance.
|
||||
client (gmqtt.Client): MQTT client instance.
|
||||
topicPrefix (str): Prefix for MQTT topics.
|
||||
homeAssistantAutoDiscoverTopic (str): Topic for Home Assistant auto-discovery.
|
||||
useCamelCaseTopicNames (bool): Flag to use camel case for topic names.
|
||||
initialized (bool): Flag indicating if the client has been initialized.
|
||||
known_topics (list): List to keep track of known topics.
|
||||
known_devices_topic (str): Dedicated topic for storing known topics.
|
||||
known_devices_topic (str): Topic for storing known devices.
|
||||
"""
|
||||
|
||||
if self._initialized:
|
||||
@@ -108,17 +90,15 @@ class MQTTClient:
|
||||
async def connect(self):
|
||||
"""
|
||||
Asynchronously connects to the MQTT broker and optionally clears the known devices topic.
|
||||
This method logs the connection attempt, connects to the MQTT broker using the specified
|
||||
broker address and port, and sets the keepalive interval. If the CLEAN_KNOWN_DEVICES
|
||||
argument is set to True, it publishes an empty message to the known devices topic to clear it.
|
||||
This function logs the connection attempt, connects to the MQTT broker using the specified
|
||||
broker address and port, and sets the keepalive interval. If the CLEAN_KNOWN_DEVICES argument
|
||||
is set, it publishes an empty message to the known devices topic to clear it.
|
||||
Args:
|
||||
None
|
||||
Returns:
|
||||
None
|
||||
Raises:
|
||||
Any exceptions raised by the underlying MQTT client library during connection.
|
||||
"""
|
||||
|
||||
|
||||
logger.info("[MQTT] Connecting to broker...")
|
||||
await self.client.connect(self.broker, self.port, keepalive=60, version=gmqtt.constants.MQTTv311)
|
||||
|
||||
@@ -128,15 +108,13 @@ class MQTTClient:
|
||||
|
||||
def subscribe_known_topics(self):
|
||||
"""
|
||||
Subscribes the MQTT client to known topics.
|
||||
This method subscribes the MQTT client to two specific topics:
|
||||
1. A topic for known devices, constructed using the topic prefix and known devices topic.
|
||||
2. A status topic for Home Assistant auto-discovery.
|
||||
The subscription QoS (Quality of Service) level for both topics is set to 1.
|
||||
Subscribe to predefined MQTT topics.
|
||||
This method subscribes the MQTT client to a set of known topics, which include:
|
||||
- A topic for known devices, constructed using the topic prefix and known devices topic.
|
||||
- A status topic for Home Assistant auto-discovery.
|
||||
The subscription is done with a QoS level of 1 for both topics.
|
||||
Logging:
|
||||
Logs an informational message indicating that the client is subscribing to known devices topic.
|
||||
Raises:
|
||||
Any exceptions raised by the gmqtt.Subscription or self.client.subscribe methods.
|
||||
- Logs an info message indicating the subscription to known devices topic.
|
||||
"""
|
||||
|
||||
logger.info("Subscribe to known devices topic")
|
||||
@@ -158,7 +136,7 @@ class MQTTClient:
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
|
||||
logger.debug('SUBSCRIBED')
|
||||
|
||||
def on_message(self, client, topic, payload, qos, properties):
|
||||
@@ -169,49 +147,46 @@ class MQTTClient:
|
||||
topic (str): The topic that the message was received on.
|
||||
payload (bytes): The message payload.
|
||||
qos (int): The quality of service level of the message.
|
||||
properties (paho.mqtt.properties.Properties): The properties of the message.
|
||||
Behavior:
|
||||
- If the topic matches the known devices topic, updates the known devices set with the retained message.
|
||||
- If the topic matches the Home Assistant auto-discover status topic, logs the status message and clears the known devices topic.
|
||||
properties (paho.mqtt.properties.Properties): The properties associated with the message.
|
||||
This function performs the following actions:
|
||||
- If the topic matches the known devices topic, it updates the known topics list with the retained message.
|
||||
- If the topic matches the Home Assistant auto-discover status topic, it logs the status message and, if the payload indicates that Home Assistant is online, it clears the known devices topic.
|
||||
"""
|
||||
|
||||
if self.known_devices_topic in topic:
|
||||
# Update the known devices set with the retained message
|
||||
self.known_topics = list(filter(None, [x.strip() for x in payload.decode().split(",")]))
|
||||
if properties['retain'] == True:
|
||||
if self.config.LOGGING['deviceAdded']:
|
||||
logger.info(f"Loaded devices from known devices Topic:")
|
||||
|
||||
for idx, devname in enumerate(self.known_topics, start=1):
|
||||
logger.info(f"Device no. {idx:<3}: {devname} ")
|
||||
else:
|
||||
logger.debug(f"Loaded devices from known devices Topic:")
|
||||
for idx, devname in enumerate(self.known_topics):
|
||||
logger.debug(f"Device added no. {idx:<3}: {devname} ")
|
||||
|
||||
|
||||
if f"{self.homeAssistantAutoDiscoverTopic}/status" == topic:
|
||||
logger.info(f"HASS Status Messages {topic} received: {payload.decode()}")
|
||||
if payload.decode() == "online":
|
||||
self._publish(f"{self.topicPrefix.replace('/', '')}/{self.known_devices_topic}", " ", retain=True)
|
||||
logger.info("Known Devices Topic have been cleared")
|
||||
|
||||
def refresh_known_devices(self, devname):
|
||||
"""
|
||||
Refreshes the list of known devices by publishing the updated list to the MQTT topic.
|
||||
Args:
|
||||
devname (str): The name of the device to be refreshed.
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
self._publish(f"{self.topicPrefix.replace('/', '')}/{self.known_devices_topic}", ",".join(self.known_topics), retain=True)
|
||||
logger.info("Known Devices Topic have been cleared")
|
||||
self.clear_hass()
|
||||
logger.info("All configuration from HASS has been resetet")
|
||||
|
||||
def on_connect(self, client, flags, rc, properties):
|
||||
"""
|
||||
Callback function for when the client receives a CONNACK response from the server.
|
||||
Args:
|
||||
client (paho.mqtt.client.Client): The client instance for this callback.
|
||||
flags (dict): Response flags sent by the broker.
|
||||
rc (int): The connection result.
|
||||
properties (paho.mqtt.properties.Properties): The properties associated with the connection.
|
||||
Returns:
|
||||
None
|
||||
Logs:
|
||||
- Info: When connected successfully with result code 0.
|
||||
- Error: When failed to connect with a non-zero result code.
|
||||
Parameters:
|
||||
client (paho.mqtt.client.Client): The client instance for this callback.
|
||||
flags (dict): Response flags sent by the broker.
|
||||
rc (int): The connection result.
|
||||
properties (paho.mqtt.properties.Properties): The properties associated with the connection.
|
||||
If the connection is successful (rc == 0), logs a success message and subscribes to known topics if any.
|
||||
Otherwise, logs an error message with the return code.
|
||||
"""
|
||||
|
||||
|
||||
if rc == 0:
|
||||
logger.info(f"Connected to MQTT with result code {rc}")
|
||||
if len(self.homeAssistantAutoDiscoverTopic) > 0:
|
||||
@@ -222,14 +197,13 @@ class MQTTClient:
|
||||
def on_disconnect(self, client, packet, exc=None):
|
||||
"""
|
||||
Callback function that is called when the client disconnects from the MQTT broker.
|
||||
This function logs the disconnection event and attempts to reconnect the client
|
||||
in case of an unexpected disconnection. It will keep trying to reconnect every
|
||||
5 seconds until successful.
|
||||
Args:
|
||||
client (paho.mqtt.client.Client): The MQTT client instance that disconnected.
|
||||
packet (paho.mqtt.client.MQTTMessage): The MQTT message packet received during disconnection.
|
||||
exc (Exception, optional): The exception that caused the disconnection, if any. Defaults to None.
|
||||
Logs:
|
||||
Logs an info message indicating disconnection.
|
||||
Logs a warning message indicating an unexpected disconnection and attempts to reconnect.
|
||||
Logs an error message if reconnection fails and retries every 5 seconds.
|
||||
packet (paho.mqtt.packet.Packet): The disconnect packet.
|
||||
exc (Exception, optional): The exception that caused the disconnection, if any.
|
||||
"""
|
||||
|
||||
logger.info(f"Disconnected with result code ")
|
||||
@@ -244,11 +218,11 @@ class MQTTClient:
|
||||
|
||||
def _publish(self, topic, payload, qos=0, retain=False):
|
||||
"""
|
||||
Publish a message to a specified MQTT topic.
|
||||
Publishes a message to a specified MQTT topic.
|
||||
Args:
|
||||
topic (str): The MQTT topic to publish to.
|
||||
payload (str): The message payload to publish.
|
||||
qos (int, optional): The Quality of Service level for message delivery. Defaults to 0.
|
||||
qos (int, optional): The Quality of Service level for the message. Defaults to 0.
|
||||
retain (bool, optional): If True, the message will be retained by the broker. Defaults to False.
|
||||
Returns:
|
||||
None
|
||||
@@ -257,33 +231,51 @@ class MQTTClient:
|
||||
logger.debug(f"MQTT Publish Topic: {topic} payload: {payload}")
|
||||
self.client.publish(f"{topic}", payload, qos, retain)
|
||||
#time.sleep(0.1)
|
||||
|
||||
def refresh_known_devices(self, devname):
|
||||
"""
|
||||
Refreshes the list of known devices by publishing the current known topics to the MQTT broker.
|
||||
Args:
|
||||
devname (str): The name of the device to refresh.
|
||||
This function constructs a topic string by replacing '/' with an empty string in the topicPrefix,
|
||||
then concatenates it with the known_devices_topic. It publishes the known topics as a comma-separated
|
||||
string to this constructed topic with the retain flag set to True.
|
||||
"""
|
||||
self.known_topics.append(devname)
|
||||
if self.config.LOGGING['deviceAdded']:
|
||||
logger.info(f"Device added no. {len(self.known_topics):<3}: {devname} ")
|
||||
else:
|
||||
logger.debug(f"Device added no. {len(self.known_topics):<3}: {devname} ")
|
||||
self._publish(f"{self.topicPrefix.replace('/', '')}/{self.known_devices_topic}", ",".join(self.known_topics), retain=True)
|
||||
|
||||
def publish_message(self, name, value):
|
||||
"""
|
||||
Publishes a message to an MQTT topic.
|
||||
This method normalizes the given name, determines the appropriate MQTT topic,
|
||||
and publishes the provided value to that topic. If Home Assistant auto-discovery
|
||||
is enabled, it will also handle the auto-discovery configuration.
|
||||
This function normalizes the given name, determines the appropriate MQTT topic,
|
||||
and publishes the provided value to that topic. It also handles Home Assistant
|
||||
auto-discovery if configured.
|
||||
Args:
|
||||
name (str): The name of the sensor or device.
|
||||
value (int, float, bool, str): The value to be published. If the value is a float,
|
||||
it will be rounded to two decimal places.
|
||||
it will be rounded to two decimal places.
|
||||
Raises:
|
||||
KeyError: If the name is not found in the NASA_REPO configuration.
|
||||
ValueError: If the value type is not supported for publishing.
|
||||
"""
|
||||
|
||||
newname = f"{self._normalize_name(name)}"
|
||||
|
||||
if len(self.homeAssistantAutoDiscoverTopic) > 0:
|
||||
|
||||
if name not in self.known_topics:
|
||||
self.auto_discover_hass(name)
|
||||
self.refresh_known_devices(name)
|
||||
|
||||
sensor_type = "sensor"
|
||||
if 'enum' in self.config.NASA_REPO[name]:
|
||||
enum = [*self.config.NASA_REPO[name]['enum'].values()]
|
||||
if all([en.lower() in ['on', 'off'] for en in enum]):
|
||||
sensor_type = "binary_sensor"
|
||||
topicname = f"{self.config.MQTT['homeAssistantAutoDiscoverTopic']}/{sensor_type}/{self.DEVICE_ID}_{newname.lower()}/state"
|
||||
if name not in self.known_topics:
|
||||
self.auto_discover_hass(topicname, name, newname, sensor_type)
|
||||
|
||||
else:
|
||||
topicname = f"{self.topicPrefix.replace('/', '')}/{newname}"
|
||||
|
||||
@@ -292,78 +284,24 @@ class MQTTClient:
|
||||
|
||||
self._publish(topicname, value, qos=2, retain=False)
|
||||
|
||||
def auto_discover_hass(self, topicname, nameraw, namenorm, sensor_type):
|
||||
"""
|
||||
Automatically discovers and configures Home Assistant entities for the MQTT client.
|
||||
This function creates and publishes a configuration payload for Home Assistant's MQTT discovery.
|
||||
It supports both sensor and binary sensor types, and sets appropriate attributes based on the
|
||||
provided sensor type and unit of measurement.
|
||||
Args:
|
||||
topicname (str): The MQTT topic name.
|
||||
nameraw (str): The raw name of the sensor.
|
||||
namenorm (str): The normalized name of the sensor.
|
||||
sensor_type (str): The type of the sensor (e.g., "sensor" or "binary_sensor").
|
||||
Returns:
|
||||
None
|
||||
def clear_hass(self):
|
||||
"""
|
||||
clears all entities/components fpr the HomeAssistant Device
|
||||
"""
|
||||
entities = {}
|
||||
for nasa in self.config.NASA_REPO:
|
||||
namenorm = self._normalize_name(nasa)
|
||||
sensor_type = self._get_sensor_type(nasa)
|
||||
entities[namenorm] = {"platform": sensor_type}
|
||||
|
||||
entity = { namenorm: {
|
||||
"name": f"{namenorm}",
|
||||
"object_id": f"{self.DEVICE_ID}_{namenorm.lower()}",
|
||||
"unique_id": f"{self.DEVICE_ID}_{nameraw.lower()}",
|
||||
"platform": sensor_type,
|
||||
"value_template": "{{ value }}",
|
||||
"state_topic": f"{self.config.MQTT['homeAssistantAutoDiscoverTopic']}/{sensor_type}/{self.DEVICE_ID}_{namenorm.lower()}/state",
|
||||
}
|
||||
}
|
||||
|
||||
if sensor_type == "sensor":
|
||||
if len(self.config.NASA_REPO[nameraw]['unit']) > 0:
|
||||
entity[namenorm]['unit_of_measurement'] = self.config.NASA_REPO[nameraw]['unit']
|
||||
if entity[namenorm]['unit_of_measurement'] == "\u00b0C":
|
||||
entity[namenorm]['device_class'] = "temperature"
|
||||
elif entity[namenorm]['unit_of_measurement'] == '%':
|
||||
entity[namenorm]['state_class'] = "measurement"
|
||||
elif entity[namenorm]['unit_of_measurement'] == 'kW':
|
||||
entity[namenorm]['device_class'] = "power"
|
||||
elif entity[namenorm]['unit_of_measurement'] == 'rpm':
|
||||
entity[namenorm]['state_class'] = "measurement"
|
||||
elif entity[namenorm]['unit_of_measurement'] == 'bar':
|
||||
entity[namenorm]['device_class'] = "pressure"
|
||||
elif entity[namenorm]['unit_of_measurement'] == 'HP':
|
||||
entity[namenorm]['device_class'] = "power"
|
||||
elif entity[namenorm]['unit_of_measurement'] == 'hz':
|
||||
entity[namenorm]['device_class'] = "frequency"
|
||||
else:
|
||||
entity[namenorm]['device_class'] = None
|
||||
else:
|
||||
entity[namenorm]['payload_on'] = "ON"
|
||||
entity[namenorm]['payload_off'] = "OFF"
|
||||
|
||||
if 'state_class' in self.config.NASA_REPO[nameraw]:
|
||||
entity[namenorm]['state_class'] = self.config.NASA_REPO[nameraw]['state_class']
|
||||
|
||||
if 'device_class' in self.config.NASA_REPO[nameraw]:
|
||||
entity[namenorm]['device_class'] = self.config.NASA_REPO[nameraw]['device_class']
|
||||
|
||||
|
||||
device = {
|
||||
"device": {
|
||||
"identifiers": self.DEVICE_ID,
|
||||
"name": "Samsung EHS",
|
||||
"manufacturer": "Samsung",
|
||||
"model": "Mono HQ Quiet",
|
||||
"sw_version": "1.0.0"
|
||||
},
|
||||
"origin": {
|
||||
"name": "EHS-Sentinel",
|
||||
"support_url": "https://github.com/echoDaveD/EHS-Sentinel"
|
||||
},
|
||||
"components": entity,
|
||||
"device": self._get_device(),
|
||||
"origin": self._get_origin(),
|
||||
"components": entities,
|
||||
"qos": 2
|
||||
}
|
||||
|
||||
logger.debug(f"Auto Discovery HomeAssistant Message: ")
|
||||
logger.debug(f"Auto Discovery HomeAssistant Clear Message: ")
|
||||
logger.debug(f"{device}")
|
||||
|
||||
self._publish(f"{self.config.MQTT['homeAssistantAutoDiscoverTopic']}/device/{self.DEVICE_ID}/config",
|
||||
@@ -371,9 +309,99 @@ class MQTTClient:
|
||||
qos=2,
|
||||
retain=True)
|
||||
|
||||
self.known_topics.append(nameraw)
|
||||
self.refresh_known_devices(nameraw)
|
||||
def auto_discover_hass(self, name):
|
||||
"""
|
||||
Automatically discovers and configures Home Assistant entities based on the NASA_REPO configuration.
|
||||
This function iterates through the NASA_REPO configuration to create and configure entities for Home Assistant.
|
||||
It determines the type of sensor (binary_sensor or sensor) based on the configuration and sets various attributes
|
||||
such as unit of measurement, device class, state class, and payloads for binary sensors. It then constructs a device
|
||||
configuration payload and publishes it to the Home Assistant MQTT discovery topic.
|
||||
The function performs the following steps:
|
||||
1. Iterates through the NASA_REPO configuration.
|
||||
2. Normalizes the name of each NASA_REPO entry.
|
||||
3. Determines the sensor type (binary_sensor or sensor) based on the 'enum' values.
|
||||
4. Configures the entity attributes such as unit of measurement, device class, state class, and payloads.
|
||||
5. Constructs a device configuration payload.
|
||||
6. Publishes the device configuration to the Home Assistant MQTT discovery topic.
|
||||
Attributes:
|
||||
entities (dict): A dictionary to store the configured entities.
|
||||
device (dict): A dictionary to store the device configuration payload.
|
||||
Logs:
|
||||
Logs the constructed device configuration payload for debugging purposes.
|
||||
Publishes:
|
||||
Publishes the device configuration payload to the Home Assistant MQTT discovery topic with QoS 2 and retain flag set to True.
|
||||
"""
|
||||
entity = {}
|
||||
namenorm = self._normalize_name(name)
|
||||
sensor_type = self._get_sensor_type(name)
|
||||
entity = {
|
||||
"name": f"{namenorm}",""
|
||||
"object_id": f"{self.DEVICE_ID}_{namenorm.lower()}",
|
||||
"unique_id": f"{self.DEVICE_ID}_{name.lower()}",
|
||||
"platform": sensor_type,
|
||||
"value_template": "{{ value }}",
|
||||
#"value_template": "{{ value if value | length > 0 else 'unavailable' }}",
|
||||
"state_topic": f"{self.config.MQTT['homeAssistantAutoDiscoverTopic']}/{sensor_type}/{self.DEVICE_ID}_{namenorm.lower()}/state",
|
||||
}
|
||||
|
||||
if sensor_type == "sensor":
|
||||
if len(self.config.NASA_REPO[name]['unit']) > 0:
|
||||
entity['unit_of_measurement'] = self.config.NASA_REPO[name]['unit']
|
||||
if entity['unit_of_measurement'] == "\u00b0C":
|
||||
entity['device_class'] = "temperature"
|
||||
elif entity['unit_of_measurement'] == '%':
|
||||
entity['state_class'] = "measurement"
|
||||
elif entity['unit_of_measurement'] == 'kW':
|
||||
entity['device_class'] = "power"
|
||||
elif entity['unit_of_measurement'] == 'rpm':
|
||||
entity['state_class'] = "measurement"
|
||||
elif entity['unit_of_measurement'] == 'bar':
|
||||
entity['device_class'] = "pressure"
|
||||
elif entity['unit_of_measurement'] == 'HP':
|
||||
entity['device_class'] = "power"
|
||||
elif entity['unit_of_measurement'] == 'hz':
|
||||
entity['device_class'] = "frequency"
|
||||
else:
|
||||
entity['device_class'] = None
|
||||
else:
|
||||
entity['payload_on'] = "ON"
|
||||
entity['payload_off'] = "OFF"
|
||||
|
||||
if 'state_class' in self.config.NASA_REPO[name]:
|
||||
entity['state_class'] = self.config.NASA_REPO[name]['state_class']
|
||||
|
||||
if 'device_class' in self.config.NASA_REPO[name]:
|
||||
entity['device_class'] = self.config.NASA_REPO[name]['device_class']
|
||||
|
||||
device = {
|
||||
"device": self._get_device(),
|
||||
"origin": self._get_origin(),
|
||||
"qos": 2
|
||||
}
|
||||
device.update(entity)
|
||||
|
||||
logger.debug(f"Auto Discovery HomeAssistant Message: ")
|
||||
logger.debug(f"{device}")
|
||||
|
||||
self._publish(f"{self.config.MQTT['homeAssistantAutoDiscoverTopic']}/{sensor_type}/{self.DEVICE_ID}_{name.lower()}/config",
|
||||
json.dumps(device, ensure_ascii=False),
|
||||
qos=2,
|
||||
retain=True)
|
||||
|
||||
def _get_device(self):
|
||||
return {
|
||||
"identifiers": self.DEVICE_ID,
|
||||
"name": "Samsung EHS",
|
||||
"manufacturer": "Samsung",
|
||||
"model": "Mono HQ Quiet",
|
||||
"sw_version": "1.0.0"
|
||||
}
|
||||
|
||||
def _get_origin(self):
|
||||
return {
|
||||
"name": "EHS-Sentinel",
|
||||
"support_url": "https://github.com/echoDaveD/EHS-Sentinel"
|
||||
}
|
||||
|
||||
def _normalize_name(self, name):
|
||||
"""
|
||||
@@ -405,3 +433,19 @@ class MQTTClient:
|
||||
tmpname = name
|
||||
|
||||
return tmpname
|
||||
|
||||
def _get_sensor_type(self, name):
|
||||
"""
|
||||
return the sensor type of given measurement
|
||||
Args:
|
||||
name (str): The name of the measurement.
|
||||
Returns:
|
||||
str: The sensor type: sensor or binary_sensor.
|
||||
"""
|
||||
sensor_type = "sensor"
|
||||
if 'enum' in self.config.NASA_REPO[name]:
|
||||
enum = [*self.config.NASA_REPO[name]['enum'].values()]
|
||||
if all([en.lower() in ['on', 'off'] for en in enum]):
|
||||
sensor_type = "binary_sensor"
|
||||
|
||||
return sensor_type
|
||||
|
||||
@@ -2,7 +2,7 @@ import asyncio
|
||||
import logging
|
||||
import traceback
|
||||
import yaml
|
||||
from CustomLogger import logger, setSilent
|
||||
from CustomLogger import logger
|
||||
from EHSArguments import EHSArguments
|
||||
from EHSConfig import EHSConfig
|
||||
from EHSExceptions import MessageWarningException
|
||||
@@ -53,7 +53,6 @@ class MessageProcessor:
|
||||
if self._initialized:
|
||||
return
|
||||
self._initialized = True
|
||||
logger.debug("init MessageProcessor")
|
||||
self.config = EHSConfig()
|
||||
self.args = EHSArguments()
|
||||
self.mqtt = MQTTClient()
|
||||
@@ -79,7 +78,10 @@ class MessageProcessor:
|
||||
raise MessageWarningException(argument=f"{msg.packet_payload}/{[hex(x) for x in msg.packet_payload]}", message=f"Value of {hexmsg} couldn't be determinate, skip Message {e}")
|
||||
self.protocolMessage(msg, msgname, msgvalue)
|
||||
else:
|
||||
logger.debug(f"Message not Found in NASA repository: {hexmsg:<6} Type: {msg.packet_message_type} Payload: {msg.packet_payload}")
|
||||
if self.config.LOGGING['messageNotFound']:
|
||||
logger.info(f"Message not Found in NASA repository: {hexmsg:<6} Type: {msg.packet_message_type} Payload: {msg.packet_payload}")
|
||||
else:
|
||||
logger.debug(f"Message not Found in NASA repository: {hexmsg:<6} Type: {msg.packet_message_type} Payload: {msg.packet_payload}")
|
||||
|
||||
def protocolMessage(self, msg: NASAMessage, msgname, msgvalue):
|
||||
"""
|
||||
@@ -98,7 +100,10 @@ class MessageProcessor:
|
||||
- Calculates and processes derived values for specific message names.
|
||||
"""
|
||||
|
||||
logger.info(f"Message number: {hex(msg.packet_message):<6} {msgname:<50} Type: {msg.packet_message_type} Payload: {msgvalue}")
|
||||
if self.config.LOGGING['proccessedMessage']:
|
||||
logger.info(f"Message number: {hex(msg.packet_message):<6} {msgname:<50} Type: {msg.packet_message_type} Payload: {msgvalue}")
|
||||
else:
|
||||
logger.debug(f"Message number: {hex(msg.packet_message):<6} {msgname:<50} Type: {msg.packet_message_type} Payload: {msgvalue}")
|
||||
|
||||
if self.config.GENERAL['protocolFile'] is not None:
|
||||
with open(self.config.GENERAL['protocolFile'], "a") as protWriter:
|
||||
@@ -110,14 +115,18 @@ class MessageProcessor:
|
||||
|
||||
if msgname in ['NASA_OUTDOOR_TW2_TEMP', 'NASA_OUTDOOR_TW1_TEMP', 'VAR_IN_FLOW_SENSOR_CALC']:
|
||||
if all(k in self.NASA_VAL_STORE for k in ['NASA_OUTDOOR_TW2_TEMP', 'NASA_OUTDOOR_TW1_TEMP', 'VAR_IN_FLOW_SENSOR_CALC']):
|
||||
self.protocolMessage(NASAMessage(packet_message=0x9999, packet_message_type=1),
|
||||
"NASA_EHSSENTINEL_HEAT_OUTPUT",
|
||||
round(
|
||||
(
|
||||
(self.NASA_VAL_STORE['NASA_OUTDOOR_TW2_TEMP'] - self.NASA_VAL_STORE['NASA_OUTDOOR_TW1_TEMP']) *
|
||||
(self.NASA_VAL_STORE['VAR_IN_FLOW_SENSOR_CALC']/60)
|
||||
* 4190
|
||||
), 4))
|
||||
value = round(
|
||||
abs(
|
||||
(self.NASA_VAL_STORE['NASA_OUTDOOR_TW2_TEMP'] - self.NASA_VAL_STORE['NASA_OUTDOOR_TW1_TEMP']) *
|
||||
(self.NASA_VAL_STORE['VAR_IN_FLOW_SENSOR_CALC']/60)
|
||||
* 4190
|
||||
) , 4
|
||||
)
|
||||
if (value < 15000 and value > 0): # only if heater output between 0 und 15000 W
|
||||
self.protocolMessage(NASAMessage(packet_message=0x9999, packet_message_type=1),
|
||||
"NASA_EHSSENTINEL_HEAT_OUTPUT",
|
||||
value
|
||||
)
|
||||
|
||||
if msgname in ('NASA_EHSSENTINEL_HEAT_OUTPUT', 'NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT'):
|
||||
if all(k in self.NASA_VAL_STORE for k in ['NASA_EHSSENTINEL_HEAT_OUTPUT', 'NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT']):
|
||||
@@ -125,6 +134,13 @@ class MessageProcessor:
|
||||
self.protocolMessage(NASAMessage(packet_message=0x9998, packet_message_type=1),
|
||||
"NASA_EHSSENTINEL_COP",
|
||||
round((self.NASA_VAL_STORE['NASA_EHSSENTINEL_HEAT_OUTPUT'] / self.NASA_VAL_STORE['NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT']/1000.), 3))
|
||||
|
||||
if msgname in ('NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT_ACCUM', 'LVAR_IN_TOTAL_GENERATED_POWER'):
|
||||
if all(k in self.NASA_VAL_STORE for k in ['NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT_ACCUM', 'LVAR_IN_TOTAL_GENERATED_POWER']):
|
||||
if (self.NASA_VAL_STORE['NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT_ACCUM'] > 0):
|
||||
self.protocolMessage(NASAMessage(packet_message=0x9997, packet_message_type=1),
|
||||
"NASA_EHSSENTINEL_TOTAL_COP",
|
||||
round(self.NASA_VAL_STORE['LVAR_IN_TOTAL_GENERATED_POWER'] / self.NASA_VAL_STORE['NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT_ACCUM'], 3))
|
||||
|
||||
def search_nasa_table(self, address):
|
||||
"""
|
||||
@@ -157,7 +173,7 @@ class MessageProcessor:
|
||||
try:
|
||||
value = eval(arithmetic)
|
||||
except Exception as e:
|
||||
logger.warning(f"Arithmetic Function couldn't been applied, using raw value: arithmetic = {arithmetic} {e}")
|
||||
logger.warning(f"Arithmetic Function couldn't been applied for Message {msgname}, using raw value: arithmetic = {arithmetic} {e}")
|
||||
value = packed_value
|
||||
else:
|
||||
value = packed_value
|
||||
|
||||
@@ -48,12 +48,53 @@ class NASAMessage:
|
||||
self.packet_message_type: int = packet_message_type
|
||||
self.packet_payload: bytes = bytes([int(hex(x), 16) for x in packet_payload])
|
||||
|
||||
|
||||
def set_packet_message(self, value: int):
|
||||
self.packet_message = value
|
||||
|
||||
def set_packet_message_type(self, value: int):
|
||||
self.packet_message_type = value
|
||||
|
||||
def set_packet_payload(self, value: list):
|
||||
self.packet_payload = bytes([int(hex(x), 16) for x in value])
|
||||
|
||||
def to_raw(self) -> bytearray:
|
||||
|
||||
message_number_reconstructed = (self.packet_message_type << 9) | (self.packet_message & 0x1FF)
|
||||
|
||||
# Extract the original bytes from message_number
|
||||
msg_rest_0 = (self.packet_message >> 8) & 0xFF # Upper 8 bits
|
||||
msg_rest_1 = self.packet_message & 0xFF # Lower 8 bits
|
||||
msgpayload = int.from_bytes(self.packet_payload, byteorder='big', signed=True)
|
||||
if self.packet_message_type == 0:
|
||||
return [
|
||||
msg_rest_0,
|
||||
msg_rest_1,
|
||||
msgpayload & 0xFF
|
||||
]
|
||||
elif self.packet_message_type == 1:
|
||||
return [
|
||||
msg_rest_0,
|
||||
msg_rest_1,
|
||||
(msgpayload >> 8) & 0xFF,
|
||||
msgpayload & 0xFF
|
||||
]
|
||||
elif self.packet_message_type == 2:
|
||||
return [
|
||||
msg_rest_0,
|
||||
msg_rest_1,
|
||||
(msgpayload >> 24) & 0xFF,
|
||||
(msgpayload >> 16) & 0xFF,
|
||||
(msgpayload >> 8) & 0xFF,
|
||||
msgpayload & 0xFF
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
f"NASAMessage(\n"
|
||||
f" packet_message={self.packet_message} ({hex(self.packet_message)}),\n"
|
||||
f" packet_message={self.packet_message} ({hex(self.packet_message)}) ({[x for x in bytearray(self.packet_message.to_bytes(2))]}),\n"
|
||||
f" packet_message_type={self.packet_message_type} ({hex(self.packet_message_type)}),\n"
|
||||
f" packet_payload={self.packet_payload} ({self.packet_payload.hex()})\n"
|
||||
f" packet_payload={self.packet_payload} ({self.packet_payload.hex()}) ({[int(x) for x in self.packet_payload]})\n"
|
||||
f")"
|
||||
)
|
||||
|
||||
|
||||
101
NASAPacket.py
101
NASAPacket.py
@@ -1,6 +1,8 @@
|
||||
from enum import Enum
|
||||
from NASAMessage import NASAMessage
|
||||
from EHSExceptions import MessageCapacityStructureWarning
|
||||
from EHSExceptions import SkipInvalidPacketException
|
||||
import binascii
|
||||
import struct
|
||||
|
||||
class AddressClassEnum(Enum):
|
||||
"""
|
||||
@@ -210,13 +212,21 @@ class NASAPacket:
|
||||
self._packet_raw = packet
|
||||
if len(packet) < 14:
|
||||
raise ValueError("Data too short to be a valid NASAPacket")
|
||||
|
||||
crc_checkusm=binascii.crc_hqx(bytearray(packet[3:-3]), 0)
|
||||
|
||||
self.packet_start = packet[0]
|
||||
self.packet_size = ((packet[1] << 8) | packet[2])
|
||||
self.packet_source_address_class = AddressClassEnum(packet[3])
|
||||
try:
|
||||
self.packet_source_address_class = AddressClassEnum(packet[3])
|
||||
except ValueError as e:
|
||||
raise SkipInvalidPacketException(f"Source Adress Class out of enum {packet[3]}")
|
||||
self.packet_source_channel = packet[4]
|
||||
self.packet_source_address = packet[5]
|
||||
self.packet_dest_address_class = AddressClassEnum(packet[6])
|
||||
try:
|
||||
self.packet_dest_address_class = AddressClassEnum(packet[6])
|
||||
except ValueError as e:
|
||||
raise SkipInvalidPacketException(f"Destination Adress Class out of enum {packet[6]}")
|
||||
self.packet_dest_channel = packet[7]
|
||||
self.packet_dest_address = packet[8]
|
||||
self.packet_information = (int(packet[9]) & 128) >> 7 == 1
|
||||
@@ -226,10 +236,13 @@ class NASAPacket:
|
||||
self.packet_data_type = DataType(int(packet[10]) & 15)
|
||||
self.packet_number = packet[11]
|
||||
self.packet_capacity = packet[12]
|
||||
self.packet_crc16 = ((packet[-3] << 8) | packet[-2]) + 2
|
||||
self.packet_crc16 = ((packet[-3] << 8) | packet[-2]) # + 2
|
||||
self.packet_end = packet[-1]
|
||||
self.packet_messages = self._extract_messages(0, self.packet_capacity, packet[13:-3], [])
|
||||
|
||||
if crc_checkusm != self.packet_crc16:
|
||||
raise SkipInvalidPacketException(f"Checksum for package could not be validated. Calculated: {crc_checkusm} in packet: {self.packet_crc16}: packet:{self}")
|
||||
|
||||
def _extract_messages(self, depth: int, capacity: int, msg_rest: bytearray, return_list: list):
|
||||
"""
|
||||
Recursively extracts messages from a bytearray and appends them to a list.
|
||||
@@ -260,7 +273,7 @@ class NASAPacket:
|
||||
elif message_type == 3:
|
||||
payload_size = len(msg_rest)
|
||||
if capacity != 1:
|
||||
raise MessageCapacityStructureWarning("Message with structure type must have capacity of 1.")
|
||||
raise SkipInvalidPacketException("Message with structure type must have capacity of 1.")
|
||||
else:
|
||||
raise ValueError(f"Mssage type unknown: {message_type}")
|
||||
|
||||
@@ -303,6 +316,84 @@ class NASAPacket:
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
# Setter methods
|
||||
def set_packet_source_address_class(self, value: AddressClassEnum):
|
||||
self.packet_source_address_class = value
|
||||
|
||||
def set_packet_source_channel(self, value: int):
|
||||
self.packet_source_channel = value
|
||||
|
||||
def set_packet_source_address(self, value: int):
|
||||
self.packet_source_address = value
|
||||
|
||||
def set_packet_dest_address_class(self, value: AddressClassEnum):
|
||||
self.packet_dest_address_class = value
|
||||
|
||||
def set_packet_dest_channel(self, value: int):
|
||||
self.packet_dest_channel = value
|
||||
|
||||
def set_packet_dest_address(self, value: int):
|
||||
self.packet_dest_address = value
|
||||
|
||||
def set_packet_information(self, value: bool):
|
||||
self.packet_information = value
|
||||
|
||||
def set_packet_version(self, value: int):
|
||||
self.packet_version = value
|
||||
|
||||
def set_packet_retry_count(self, value: int):
|
||||
self.packet_retry_count = value
|
||||
|
||||
def set_packet_type(self, value: PacketType):
|
||||
self.packet_type = value
|
||||
|
||||
def set_packet_data_type(self, value: DataType):
|
||||
self.packet_data_type = value
|
||||
|
||||
def set_packet_number(self, value: int):
|
||||
self.packet_number = value
|
||||
|
||||
def set_packet_messages(self, value: list[NASAMessage]):
|
||||
self.packet_messages = value
|
||||
|
||||
def to_raw(self) -> bytearray:
|
||||
"""
|
||||
Converts the NASAPacket object back to its raw byte representation.
|
||||
Returns:
|
||||
bytearray: The raw byte representation of the packet.
|
||||
"""
|
||||
self.packet_start = 50
|
||||
self.packet_end = 52
|
||||
|
||||
|
||||
packet = bytearray()
|
||||
packet.append(int(self.packet_start))
|
||||
packet.append(0)
|
||||
packet.append(0)
|
||||
packet.append(self.packet_source_address_class.value)
|
||||
packet.append(self.packet_source_channel)
|
||||
packet.append(self.packet_source_address)
|
||||
packet.append(self.packet_dest_address_class.value)
|
||||
packet.append(self.packet_dest_channel)
|
||||
packet.append(self.packet_dest_address)
|
||||
packet.append((self.packet_information << 7) | (self.packet_version << 5) | (self.packet_retry_count << 3))
|
||||
packet.append((self.packet_type.value << 4) | self.packet_data_type.value)
|
||||
packet.append(self.packet_number)
|
||||
packet.append(len(self.packet_messages))
|
||||
# Add messages to the packet
|
||||
for msg in self.packet_messages:
|
||||
for msg_pack in msg.to_raw():
|
||||
packet.append(msg_pack)
|
||||
self.packet_capacity = len(self.packet_messages)
|
||||
self.packet_size = len(packet)+2+2
|
||||
packet[1] = (self.packet_size >> 8) & 0xFF
|
||||
packet[2] = self.packet_size & 0xFF
|
||||
self.packet_crc16=binascii.crc_hqx(packet[3:], 0)
|
||||
final_packet = struct.pack(">BH", packet[0], len(packet[1:])+2) + packet[3:] + struct.pack(">HB", self.packet_crc16, 0x34)
|
||||
print([x for x in final_packet])
|
||||
return final_packet
|
||||
|
||||
# Example usage:
|
||||
# packet = NASAPacket()
|
||||
# packet.parse(bytearray([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
|
||||
|
||||
134
README.md
134
README.md
@@ -169,11 +169,20 @@ The `config.yml` file contains configuration settings for the EHS-Sentinel proje
|
||||
|
||||
- **nasaRepositoryFile**: Path to the NASA repository file.
|
||||
- Default: `data/NasaRepository.yml`
|
||||
- **silentMode**: Boolean flag to enable or disable silent mode. In Silent Mode only Logmessages above WARNING are printed out (for production use to not spam your systemlog)
|
||||
- Default: `True`
|
||||
- **protocolFile**: Path to the protocol file. (not set in Sample config.yml)
|
||||
- Example: `prot.csv`
|
||||
|
||||
### Logging Settings
|
||||
|
||||
- **deviceAdded**: Set to true will log when new device is added to known Devices (and discover to HASS).
|
||||
- Default: `True`
|
||||
- **messageNotFound**: Set to true will log when a received message was not found in NasaRepository
|
||||
- Default: `False`
|
||||
- **packetNotFromIndoorOutdoor**: Set to true will log when a message not from Indoor/Outdoor unit was received
|
||||
- Default: `False`
|
||||
- **proccessedMessage**: set to true, prints out a summary of which massage was processed and its value
|
||||
- Default: `False`
|
||||
|
||||
### Serial Connection Settings
|
||||
|
||||
- **device**: The serial device URL.
|
||||
@@ -205,8 +214,12 @@ The `config.yml` file contains configuration settings for the EHS-Sentinel proje
|
||||
```yaml
|
||||
general:
|
||||
nasaRepositoryFile: data/NasaRepository.yml
|
||||
silentMode: False
|
||||
protocolFile: prot.csv
|
||||
logging:
|
||||
deviceAdded: True
|
||||
messageNotFound: False
|
||||
packetNotFromIndoorOutdoor: False
|
||||
proccessedMessage: False
|
||||
serial:
|
||||
device: /dev/ttyUSB0
|
||||
baudrate: 9600
|
||||
@@ -254,5 +267,120 @@ if you want to see how many uniquie Messages have been collected in the Dumpfile
|
||||
|
||||
# Changelog
|
||||
|
||||
### v0.2.0 - 2025-02-22
|
||||
- improved MQTT Auto Discovery Config Messages
|
||||
- NASAPacket and NASAMessage are now bidirectional, can decode and encode Packets
|
||||
- Improved data quality
|
||||
- Added crc16 Checksum check for any Packet to reduce incorrect value changes
|
||||
- Only Packets from outdoor/Indoor Units are processed
|
||||
- Folloiwng warnings moved to SkipInvalidPacketException and from warning to debug log level to reduce log entries
|
||||
- Source Adress Class out of enum
|
||||
- Destination Adress Class out of enum
|
||||
- Checksum for package could not be validatet calculated
|
||||
- Message with structure type must have capacity of 1.
|
||||
- removed silentMNode config property (new logging section is replacing its functionality but more granular)
|
||||
- added new logging config property to allow to turn on/off additional info log entries
|
||||
- deviceAdded set to true (default) will log when new device is added to known Devices (and discover to HASS)
|
||||
- messageNotFound set to true (false is default) will log when a received message was not found in NasaRepository
|
||||
- packetNotFromIndoorOutdoor set to true (false is default) will log when a message not from Indoor/Outdoor unit was received
|
||||
- proccessedMessage set to true(false is default) prints out a summary of which massage was processed and its value
|
||||
- Added new Measurements
|
||||
- 0x4423 LVAR_IN_MINUTES_SINCE_INSTALLATION
|
||||
- 0x4424 LVAR_IN_MINUTES_ACTIVE
|
||||
- 0x4426 LVAR_IN_GENERATED_POWER_LAST_MINUTE
|
||||
- 0x4427 LVAR_IN_TOTAL_GENERATED_POWER
|
||||
- 0x0997 NASA_EHSSENTINEL_TOTAL_COP = LVAR_IN_TOTAL_GENERATED_POWER / NASA_OUTDOOR_CONTROL_WATTMETER_ALL_UNIT_ACCUM
|
||||
- NASA Repository, measurements enums completed
|
||||
- ENUM_IN_FSV_3041: enum edited
|
||||
- ENUM_IN_FSV_3071: enum edited
|
||||
- ENUM_IN_FSV_4021: enum edited
|
||||
- ENUM_IN_FSV_4041: enum edited
|
||||
- ENUM_IN_FSV_4051: enum edited
|
||||
- ENUM_IN_FSV_4053: enum edited
|
||||
- ENUM_IN_FSV_5022: enum edited
|
||||
- ENUM_IN_FSV_5042: enum edited
|
||||
- ENUM_IN_FSV_5081: enum edited
|
||||
- ENUM_IN_FSV_5091: enum edited
|
||||
- ENUM_IN_FSV_2093: enum edited
|
||||
- ENUM_IN_FSV_2094: enum edited
|
||||
- VAR_IN_FSV_2011: desc edited
|
||||
- VAR_IN_FSV_2012: desc edited
|
||||
- VAR_IN_FSV_2021: desc edited
|
||||
- VAR_IN_FSV_2022: desc edited
|
||||
- VAR_IN_FSV_2031: desc edited
|
||||
- VAR_IN_FSV_2032: desc edited
|
||||
- ENUM_IN_FSV_2041: desc edited
|
||||
- VAR_IN_FSV_2051: desc edited
|
||||
- VAR_IN_FSV_2052: desc edited
|
||||
- VAR_IN_FSV_2061: desc edited
|
||||
- VAR_IN_FSV_2062: desc edited
|
||||
- VAR_IN_FSV_2071: desc edited
|
||||
- VAR_IN_FSV_2072: desc edited
|
||||
- ENUM_IN_FSV_2093: desc edited
|
||||
- VAR_IN_FSV_3021: desc edited
|
||||
- VAR_IN_FSV_3022: desc edited
|
||||
- VAR_IN_FSV_3023: desc edited
|
||||
- VAR_IN_FSV_3024: desc edited
|
||||
- VAR_IN_FSV_3025: desc edited
|
||||
- VAR_IN_FSV_3026: desc edited
|
||||
- VAR_IN_FSV_3032: desc edited
|
||||
- VAR_IN_FSV_3033: desc edited
|
||||
- VAR_IN_FSV_3041: desc edited
|
||||
- VAR_IN_FSV_3042: desc edited
|
||||
- VAR_IN_FSV_3043: desc edited
|
||||
- VAR_IN_FSV_3044: desc edited
|
||||
- VAR_IN_FSV_3045: desc edited
|
||||
- VAR_IN_FSV_3046: desc edited
|
||||
- ENUM_IN_FSV_3051: desc edited
|
||||
- ENUM_IN_FSV_3052: desc edited
|
||||
- ENUM_IN_FSV_3071: desc edited
|
||||
- ENUM_IN_FSV_3081: desc edited
|
||||
- ENUM_IN_FSV_3082: desc edited
|
||||
- ENUM_IN_FSV_3083: desc edited
|
||||
- VAR_IN_FSV_4011: desc edited
|
||||
- VAR_IN_FSV_4012: desc edited
|
||||
- VAR_IN_FSV_4013: desc edited
|
||||
- VAR_IN_FSV_4021: desc edited
|
||||
- VAR_IN_FSV_4022: desc edited
|
||||
- VAR_IN_FSV_4023: desc edited
|
||||
- VAR_IN_FSV_4024: desc edited
|
||||
- VAR_IN_FSV_4025: desc edited
|
||||
- VAR_IN_FSV_4031: desc edited
|
||||
- VAR_IN_FSV_4032: desc edited
|
||||
- VAR_IN_FSV_4033: desc edited
|
||||
- VAR_IN_FSV_4041: desc edited
|
||||
- VAR_IN_FSV_4042: desc edited
|
||||
- VAR_IN_FSV_4043: desc edited
|
||||
- VAR_IN_FSV_4044: desc edited
|
||||
- VAR_IN_FSV_4045: desc edited
|
||||
- VAR_IN_FSV_4046: desc edited
|
||||
- VAR_IN_FSV_4051: desc edited
|
||||
- VAR_IN_FSV_4052: desc edited
|
||||
- VAR_IN_FSV_4053: desc edited
|
||||
- VAR_IN_FSV_4061: desc edited
|
||||
- VAR_IN_FSV_5011: desc edited
|
||||
- VAR_IN_FSV_5012: desc edited
|
||||
- VAR_IN_FSV_5013: desc edited
|
||||
- VAR_IN_FSV_5014: desc edited
|
||||
- VAR_IN_FSV_5015: desc edited
|
||||
- VAR_IN_FSV_5016: desc edited
|
||||
- VAR_IN_FSV_5017: desc edited
|
||||
- VAR_IN_FSV_5018: desc edited
|
||||
- VAR_IN_FSV_5019: desc edited
|
||||
- VAR_IN_FSV_5021: desc edited
|
||||
- VAR_IN_FSV_5023: desc edited
|
||||
- ENUM_IN_FSV_5022: desc edited
|
||||
- ENUM_IN_FSV_5041: desc edited
|
||||
- ENUM_IN_FSV_5042: desc edited
|
||||
- ENUM_IN_FSV_5043: desc edited
|
||||
- ENUM_IN_FSV_5051: desc edited
|
||||
- VAR_IN_FSV_5083: desc edited
|
||||
- VAR_IN_FSV_5082: desc edited
|
||||
- ENUM_IN_FSV_5081: desc edited
|
||||
- ENUM_IN_FSV_5091: desc edited
|
||||
- ENUM_IN_FSV_5094: desc edited
|
||||
- VAR_IN_FSV_5092: desc edited
|
||||
- VAR_IN_FSV_5093: desc edited
|
||||
|
||||
### v0.1.0Beta - 2025-02-08
|
||||
- Initial Commit
|
||||
@@ -203,8 +203,9 @@ enum:
|
||||
ENUM_IN_FSV_2041:
|
||||
address: '0x4093'
|
||||
arithmetic: ''
|
||||
description: FSV Water Law Type Heating
|
||||
description: Heating - Heating WL Selection WL Type
|
||||
enum:
|
||||
0x00: 'Unknown'
|
||||
0x01: 'Floor'
|
||||
0x02: 'FCU'
|
||||
remarks: 1 Floor, 2 FCU
|
||||
@@ -214,8 +215,9 @@ ENUM_IN_FSV_2041:
|
||||
ENUM_IN_FSV_2081:
|
||||
address: '0x4094'
|
||||
arithmetic: ''
|
||||
description: FSV Water Law Type Cooling
|
||||
description: Cooling - Cooling WL Selection WL Type
|
||||
enum:
|
||||
0x00: 'Unknown'
|
||||
0x01: 'Floor'
|
||||
0x02: 'FCU'
|
||||
remarks: 1 Floor, 2 FCU
|
||||
@@ -225,12 +227,12 @@ ENUM_IN_FSV_2081:
|
||||
ENUM_IN_FSV_2093:
|
||||
address: '0x4127'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Remote Controller - Remote Controller Room Temp. Control
|
||||
enum:
|
||||
0x01: 'one'
|
||||
0x02: 'two'
|
||||
0x03: 'three'
|
||||
0x04: 'four'
|
||||
0x01: 'Off (1min delay) by Room Sensor'
|
||||
0x02: 'Off (1min delay) by Room Sensor or WL'
|
||||
0x03: 'On'
|
||||
0x04: 'Repeat 3min On/7min Off by Room Sensor or WL'
|
||||
remarks: Min = 1 Max = 4
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -245,6 +247,7 @@ ENUM_IN_FSV_2094:
|
||||
0x02: 'two'
|
||||
0x03: 'three'
|
||||
0x04: 'four'
|
||||
0xFF: 'off'
|
||||
remarks: values 0="No" up to 4="4"
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -252,10 +255,10 @@ ENUM_IN_FSV_2094:
|
||||
ENUM_IN_FSV_3041:
|
||||
address: '0x4099'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Disinfection Application
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
0x00: 'Off'
|
||||
0x01: 'on'
|
||||
remarks: 0 No, 1 Yes
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -263,7 +266,7 @@ ENUM_IN_FSV_3041:
|
||||
ENUM_IN_FSV_3042:
|
||||
address: '0x409A'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Disinfection Interval
|
||||
enum:
|
||||
0x00: 'Sunday'
|
||||
0x01: 'Monday'
|
||||
@@ -280,7 +283,7 @@ ENUM_IN_FSV_3042:
|
||||
ENUM_IN_FSV_3051:
|
||||
address: '0x409B'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Forced DHW Operation Timer OFF Function
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
@@ -291,7 +294,10 @@ ENUM_IN_FSV_3051:
|
||||
ENUM_IN_FSV_3071:
|
||||
address: '0x409D'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Direction of 3Way Valve DHW Tank
|
||||
enum:
|
||||
0x00: 'Room'
|
||||
0x01: 'Tank'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -299,7 +305,7 @@ ENUM_IN_FSV_3071:
|
||||
ENUM_IN_FSV_4011:
|
||||
address: '0x409E'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Heat Pump Heating/ DHW Priority
|
||||
enum:
|
||||
0x00: 'DHW'
|
||||
0x01: 'Heating'
|
||||
@@ -310,11 +316,11 @@ ENUM_IN_FSV_4011:
|
||||
ENUM_IN_FSV_4021:
|
||||
address: '0x409F'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Backup Heater Application
|
||||
enum:
|
||||
0x00: 'zero'
|
||||
0x01: 'one'
|
||||
0x02: 'two'
|
||||
0x00: 'No'
|
||||
0x01: '2 Step BUH1+BUH2'
|
||||
0x02: '1 Step BUH2'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -322,7 +328,7 @@ ENUM_IN_FSV_4021:
|
||||
ENUM_IN_FSV_4022:
|
||||
address: '0x40A0'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Backup Heater BUH/BSH Priority
|
||||
enum:
|
||||
0x00: 'BUH_BSH_Both'
|
||||
0x01: 'BUH'
|
||||
@@ -334,7 +340,7 @@ ENUM_IN_FSV_4022:
|
||||
ENUM_IN_FSV_4023:
|
||||
address: '0x40A1'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Backup Heater Cold Weather Compensation
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
@@ -345,7 +351,7 @@ ENUM_IN_FSV_4023:
|
||||
ENUM_IN_FSV_4031:
|
||||
address: '0x40A2'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Backup Boiler Application
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
@@ -356,7 +362,7 @@ ENUM_IN_FSV_4031:
|
||||
ENUM_IN_FSV_4032:
|
||||
address: '0x40A3'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Backup Boiler Priority
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
@@ -367,11 +373,11 @@ ENUM_IN_FSV_4032:
|
||||
ENUM_IN_FSV_4041:
|
||||
address: '0x40C0'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Mixing Valve Application
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'one'
|
||||
0x02: 'two'
|
||||
0x01: 'FSV_TARGET_DELTA'
|
||||
0x02: 'WL'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -379,7 +385,13 @@ ENUM_IN_FSV_4041:
|
||||
ENUM_IN_FSV_4044:
|
||||
address: '0x40C1'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Mixing Valve Control Factor
|
||||
enum:
|
||||
0x01: '1'
|
||||
0x02: '2'
|
||||
0x03: '3'
|
||||
0x04: '4'
|
||||
0x05: '5'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -387,10 +399,11 @@ ENUM_IN_FSV_4044:
|
||||
ENUM_IN_FSV_4051:
|
||||
address: '0x40C2'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Inverter Pump Application
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
0x01: '100%'
|
||||
0x02: '70%'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -398,10 +411,11 @@ ENUM_IN_FSV_4051:
|
||||
ENUM_IN_FSV_4053:
|
||||
address: '0x40C3'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Inverter Pump Control Factor
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
0x01: '1'
|
||||
0x02: '2'
|
||||
0x03: '3'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -409,10 +423,10 @@ ENUM_IN_FSV_4053:
|
||||
ENUM_IN_FSV_4061:
|
||||
address: '0x411A'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Zone Control Application
|
||||
enum:
|
||||
0x00: 'zero'
|
||||
0x01: 'one'
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -420,10 +434,10 @@ ENUM_IN_FSV_4061:
|
||||
ENUM_IN_FSV_5022:
|
||||
address: '0x4128'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW Saving - DHW Saving Mode
|
||||
enum:
|
||||
0x00: 'min'
|
||||
0x01: 'max'
|
||||
0x00: 'ON'
|
||||
0x01: 'OFF'
|
||||
remarks: Min = 0 Max = 1
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -442,7 +456,7 @@ ENUM_IN_FSV_5033:
|
||||
ENUM_IN_FSV_5041:
|
||||
address: '0x40A4'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Power Peak Control - Application
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
@@ -453,12 +467,12 @@ ENUM_IN_FSV_5041:
|
||||
ENUM_IN_FSV_5042:
|
||||
address: '0x40A5'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Power Peak Control - Select Forced Off Parts
|
||||
enum:
|
||||
0x00: 'All'
|
||||
0x01: 'one'
|
||||
0x02: 'two'
|
||||
0x03: 'three'
|
||||
0x00: 'COMP_PER_BUH_OFF_BSH_PER'
|
||||
0x01: 'COMP_PER_BUH_OFF_BSH_OFF'
|
||||
0x02: 'COMP_OFF_BUH_OFF_BSH_PER'
|
||||
0x03: 'COMP_OFF_BUH_OFF_BSH_OFF'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -466,7 +480,7 @@ ENUM_IN_FSV_5042:
|
||||
ENUM_IN_FSV_5043:
|
||||
address: '0x40A6'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Power Peak Control - Using Input Voltage
|
||||
enum:
|
||||
0x00: 'Low'
|
||||
0x01: 'High'
|
||||
@@ -477,10 +491,10 @@ ENUM_IN_FSV_5043:
|
||||
ENUM_IN_FSV_5051:
|
||||
address: '0x40A7'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Frequency Ratio Control
|
||||
enum:
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
0x00: 'Disable'
|
||||
0x01: 'Use'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -499,10 +513,10 @@ ENUM_IN_FSV_5061:
|
||||
ENUM_IN_FSV_5081:
|
||||
address: '0x411B'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: PV Control - Application
|
||||
enum:
|
||||
0x00: 'zero'
|
||||
0x01: 'one'
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -510,10 +524,10 @@ ENUM_IN_FSV_5081:
|
||||
ENUM_IN_FSV_5091:
|
||||
address: '0x411C'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Smart Grid Control - Application
|
||||
enum:
|
||||
0x00: 'zero'
|
||||
0x01: 'one'
|
||||
0x00: 'No'
|
||||
0x01: 'Yes'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -521,10 +535,10 @@ ENUM_IN_FSV_5091:
|
||||
ENUM_IN_FSV_5094:
|
||||
address: '0x411D'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Smart Grid Control - DHW Mode
|
||||
enum:
|
||||
0x00: 'zero'
|
||||
0x01: 'one'
|
||||
0x00: '55° by HP'
|
||||
0x01: '70° by HP and BSH'
|
||||
remarks: ''
|
||||
signed: ''
|
||||
type: ENUM
|
||||
@@ -1227,6 +1241,45 @@ LVAR_IN_ETO_HEAT_CONTROL_DATA:
|
||||
signed: 'false'
|
||||
type: LVAR
|
||||
unit: ''
|
||||
LVAR_IN_MINUTES_SINCE_INSTALLATION:
|
||||
address: '0x4423'
|
||||
arithmetic: ''
|
||||
description: Minutes since installation
|
||||
remarks:
|
||||
state_class: total_increasing
|
||||
device_class: duration
|
||||
signed: 'false'
|
||||
type: LVAR
|
||||
unit: 'min'
|
||||
LVAR_IN_MINUTES_ACTIVE:
|
||||
address: '0x4424'
|
||||
arithmetic: ''
|
||||
description: Minutes active
|
||||
remarks:
|
||||
state_class: total_increasing
|
||||
device_class: duration
|
||||
signed: 'false'
|
||||
type: LVAR
|
||||
unit: 'min'
|
||||
LVAR_IN_GENERATED_POWER_LAST_MINUTE:
|
||||
address: '0x4426'
|
||||
arithmetic: value / 1000
|
||||
description: Generated power last minute
|
||||
remarks: value is kWh, so do div 1000
|
||||
device_class: energy
|
||||
signed: 'false'
|
||||
type: LVAR
|
||||
unit: kWh
|
||||
LVAR_IN_TOTAL_GENERATED_POWER:
|
||||
address: '0x4427'
|
||||
arithmetic: value / 1000
|
||||
description: Total generated power
|
||||
remarks: value is kWh, so do div 1000
|
||||
state_class: total_increasing
|
||||
device_class: energy
|
||||
signed: 'false'
|
||||
type: LVAR
|
||||
unit: kWh
|
||||
LVAR_OUT_AUTO_INSPECT_RESULT0:
|
||||
address: '0x840B'
|
||||
arithmetic: ''
|
||||
@@ -2752,7 +2805,7 @@ NASA_OUTDOOR_COMP2_TARGET_HZ:
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
uunit: 'Hz'
|
||||
unit: 'Hz'
|
||||
NASA_OUTDOOR_COMP3_ORDER_HZ:
|
||||
address: '0x82C0'
|
||||
arithmetic: ''
|
||||
@@ -3295,12 +3348,12 @@ NASA_OUTDOOR_HOTGAS2:
|
||||
unit: ''
|
||||
NASA_OUTDOOR_HP:
|
||||
address: '0x8287'
|
||||
arithmetic: ''
|
||||
description: Outdoor unit horsepower
|
||||
arithmetic: 'value * 0.7457'
|
||||
description: Outdoor unit horsepower (in kw)
|
||||
remarks: unknown UNIT "HP"
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
unit: HP
|
||||
unit: kw
|
||||
NASA_OUTDOOR_HREEV:
|
||||
address: '0x822F'
|
||||
arithmetic: ''
|
||||
@@ -4820,7 +4873,7 @@ VAR_IN_FLOW_SENSOR_VOLTAGE:
|
||||
VAR_IN_FSV_2011:
|
||||
address: '0x4254'
|
||||
arithmetic: value / 10
|
||||
description: Water Law Auto heating ambient temperature - Max.
|
||||
description: Heating - Outdoor Temp. for WL Max.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4828,7 +4881,7 @@ VAR_IN_FSV_2011:
|
||||
VAR_IN_FSV_2012:
|
||||
address: '0x4255'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Outdoor Temp. for WL Min.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4836,7 +4889,7 @@ VAR_IN_FSV_2012:
|
||||
VAR_IN_FSV_2021:
|
||||
address: '0x4256'
|
||||
arithmetic: value / 10
|
||||
description: Water Law (WL1-Floor) Temperature auto heating - Max.
|
||||
description: Heating - Water out Temp. UFH Max.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4844,7 +4897,7 @@ VAR_IN_FSV_2021:
|
||||
VAR_IN_FSV_2022:
|
||||
address: '0x4257'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Water out Temp. UFH Min.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4852,7 +4905,7 @@ VAR_IN_FSV_2022:
|
||||
VAR_IN_FSV_2031:
|
||||
address: '0x4258'
|
||||
arithmetic: value / 10
|
||||
description: Water Law (WL2-FCU) Temperature auto heating - Max.
|
||||
description: Heating - Water out Temp. FCU Max.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4860,7 +4913,7 @@ VAR_IN_FSV_2031:
|
||||
VAR_IN_FSV_2032:
|
||||
address: '0x4259'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Water out Temp. FCU Min.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4868,7 +4921,7 @@ VAR_IN_FSV_2032:
|
||||
VAR_IN_FSV_2051:
|
||||
address: '0x425A'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Cooling - Outdoor Temp. for WL Max.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4876,7 +4929,7 @@ VAR_IN_FSV_2051:
|
||||
VAR_IN_FSV_2052:
|
||||
address: '0x425B'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Cooling - Outdoor Temp. for WL Min.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4884,7 +4937,7 @@ VAR_IN_FSV_2052:
|
||||
VAR_IN_FSV_2061:
|
||||
address: '0x425C'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Cooling - Water out Temp. UFH Max.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4892,7 +4945,7 @@ VAR_IN_FSV_2061:
|
||||
VAR_IN_FSV_2062:
|
||||
address: '0x425D'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Cooling - Water out Temp. UFH Min.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4900,7 +4953,7 @@ VAR_IN_FSV_2062:
|
||||
VAR_IN_FSV_2071:
|
||||
address: '0x425E'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Cooling - Water out Temp. FCU Max.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4908,7 +4961,7 @@ VAR_IN_FSV_2071:
|
||||
VAR_IN_FSV_2072:
|
||||
address: '0x425F'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Cooling - Water out Temp. FCU Min.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4916,7 +4969,7 @@ VAR_IN_FSV_2072:
|
||||
VAR_IN_FSV_3021:
|
||||
address: '0x4260'
|
||||
arithmetic: value / 10
|
||||
description: DHW Heating mode - Max.
|
||||
description: DHW - Heat Pump Max. temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4924,7 +4977,7 @@ VAR_IN_FSV_3021:
|
||||
VAR_IN_FSV_3022:
|
||||
address: '0x4261'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: DHW - Heat Pump Stop
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4932,7 +4985,7 @@ VAR_IN_FSV_3022:
|
||||
VAR_IN_FSV_3023:
|
||||
address: '0x4262'
|
||||
arithmetic: value / 10
|
||||
description: DHW Heating mode - Start
|
||||
description: DHW - Heat Pump Start
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4940,7 +4993,7 @@ VAR_IN_FSV_3023:
|
||||
VAR_IN_FSV_3024:
|
||||
address: '0x4263'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Heat Pump Min. Space heating operation time
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -4948,7 +5001,7 @@ VAR_IN_FSV_3024:
|
||||
VAR_IN_FSV_3025:
|
||||
address: '0x4264'
|
||||
arithmetic: ''
|
||||
description: DHW Heating mode - DHW operation time
|
||||
description: DHW - Heat Pump Max. DHW operation time
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -4956,7 +5009,7 @@ VAR_IN_FSV_3025:
|
||||
VAR_IN_FSV_3026:
|
||||
address: '0x4265'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Heat Pump Max. Space heating operation time
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -4964,7 +5017,7 @@ VAR_IN_FSV_3026:
|
||||
VAR_IN_FSV_3032:
|
||||
address: '0x4266'
|
||||
arithmetic: ''
|
||||
description: DHW Booster heater - Delayed time
|
||||
description: DHW - Booster Heat Delay Time
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -4972,7 +5025,7 @@ VAR_IN_FSV_3032:
|
||||
VAR_IN_FSV_3033:
|
||||
address: '0x4267'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: DHW - Booster Heat Overshoot
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -4988,7 +5041,7 @@ VAR_IN_FSV_3034:
|
||||
VAR_IN_FSV_3043:
|
||||
address: '0x4269'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Disinfection Start Time
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -4996,7 +5049,7 @@ VAR_IN_FSV_3043:
|
||||
VAR_IN_FSV_3044:
|
||||
address: '0x426A'
|
||||
arithmetic: value / 10
|
||||
description: Desinfection - Target temp.
|
||||
description: DHW - Disinfection Target Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5004,7 +5057,7 @@ VAR_IN_FSV_3044:
|
||||
VAR_IN_FSV_3045:
|
||||
address: '0x426B'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Disinfection Duration
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5012,7 +5065,7 @@ VAR_IN_FSV_3045:
|
||||
VAR_IN_FSV_3046:
|
||||
address: '0x42CE'
|
||||
arithmetic: value / 60
|
||||
description: DHW Desinfection - Max. operation time
|
||||
description: DHW - Disinfection Max time
|
||||
remarks: NASA Value is [minutes], not [hours]
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5020,7 +5073,7 @@ VAR_IN_FSV_3046:
|
||||
VAR_IN_FSV_3052:
|
||||
address: '0x426C'
|
||||
arithmetic: value / 0.1
|
||||
description: ''
|
||||
description: DHW - Forced DHW Operation Time Duration
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5028,7 +5081,7 @@ VAR_IN_FSV_3052:
|
||||
VAR_IN_FSV_3081:
|
||||
address: '0x42ED'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Energy Metering BUH 1 step capacity
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5036,7 +5089,7 @@ VAR_IN_FSV_3081:
|
||||
VAR_IN_FSV_3082:
|
||||
address: '0x42EE'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Energy Metering BUH 2 step capacity
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5044,7 +5097,7 @@ VAR_IN_FSV_3082:
|
||||
VAR_IN_FSV_3083:
|
||||
address: '0x42EF'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: DHW - Energy Metering BSH capacity
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5052,7 +5105,7 @@ VAR_IN_FSV_3083:
|
||||
VAR_IN_FSV_4012:
|
||||
address: '0x426D'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Heat Pump Outdoor Temp. for Priority
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5060,7 +5113,7 @@ VAR_IN_FSV_4012:
|
||||
VAR_IN_FSV_4013:
|
||||
address: '0x426E'
|
||||
arithmetic: value / 10
|
||||
description: Heating mode - Heating Off
|
||||
description: Heating - Heat Pump Outdoor Heat OFF
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5076,7 +5129,7 @@ VAR_IN_FSV_4014:
|
||||
VAR_IN_FSV_4024:
|
||||
address: '0x4270'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Backup Heater Threshold Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5084,7 +5137,7 @@ VAR_IN_FSV_4024:
|
||||
VAR_IN_FSV_4025:
|
||||
address: '0x4271'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Backup Heater Defrost Backup Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5092,7 +5145,7 @@ VAR_IN_FSV_4025:
|
||||
VAR_IN_FSV_4033:
|
||||
address: '0x4272'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Backup Boiler Threshold Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5100,7 +5153,7 @@ VAR_IN_FSV_4033:
|
||||
VAR_IN_FSV_4042:
|
||||
address: '0x4286'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Mixing Valve Target Delta Heating
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5108,7 +5161,7 @@ VAR_IN_FSV_4042:
|
||||
VAR_IN_FSV_4043:
|
||||
address: '0x4287'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Mixing Valve Target Delta Cooling
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5116,7 +5169,7 @@ VAR_IN_FSV_4043:
|
||||
VAR_IN_FSV_4045:
|
||||
address: '0x4288'
|
||||
arithmetic: ''
|
||||
description: ''
|
||||
description: Heating - Mixing Valve Control Interval
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5124,7 +5177,7 @@ VAR_IN_FSV_4045:
|
||||
VAR_IN_FSV_4046:
|
||||
address: '0x4289'
|
||||
arithmetic: value / 0.1
|
||||
description: ''
|
||||
description: Heating - Mixing Valve Running Time
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5132,7 +5185,7 @@ VAR_IN_FSV_4046:
|
||||
VAR_IN_FSV_4052:
|
||||
address: '0x428A'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Heating - Inverter Pump Target Delta
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5140,7 +5193,7 @@ VAR_IN_FSV_4052:
|
||||
VAR_IN_FSV_5011:
|
||||
address: '0x4273'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Outing Mode - Water Out Temp. for Cooling
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5148,7 +5201,7 @@ VAR_IN_FSV_5011:
|
||||
VAR_IN_FSV_5012:
|
||||
address: '0x4274'
|
||||
arithmetic: value / 10
|
||||
description: Outing mode - Room Temperature of cooling Mode
|
||||
description: Outing mode - Room Temp. for Cooling
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5156,7 +5209,7 @@ VAR_IN_FSV_5012:
|
||||
VAR_IN_FSV_5013:
|
||||
address: '0x4275'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Outing mode - Water Out Temp. for Heating
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5164,7 +5217,7 @@ VAR_IN_FSV_5013:
|
||||
VAR_IN_FSV_5014:
|
||||
address: '0x4276'
|
||||
arithmetic: value / 10
|
||||
description: Outing mode- Indoor heating temperature
|
||||
description: Outing mode - Room Temp. for Heating
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5172,7 +5225,7 @@ VAR_IN_FSV_5014:
|
||||
VAR_IN_FSV_5015:
|
||||
address: '0x4277'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Outing mode - Auto Cooling WL1 Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5180,7 +5233,7 @@ VAR_IN_FSV_5015:
|
||||
VAR_IN_FSV_5016:
|
||||
address: '0x4278'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Outing mode - Auto Cooling WL2 Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5188,7 +5241,7 @@ VAR_IN_FSV_5016:
|
||||
VAR_IN_FSV_5017:
|
||||
address: '0x4279'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Outing mode - Auto Heating WL1 Temp
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5196,7 +5249,7 @@ VAR_IN_FSV_5017:
|
||||
VAR_IN_FSV_5018:
|
||||
address: '0x427A'
|
||||
arithmetic: value / 10
|
||||
description: Outing mode - Temperature of auto heating WL2 water
|
||||
description: Outing mode - Auto Heating WL2 Temp
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5204,7 +5257,7 @@ VAR_IN_FSV_5018:
|
||||
VAR_IN_FSV_5019:
|
||||
address: '0x427B'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Outing mode - Target Tank Temp
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5212,7 +5265,7 @@ VAR_IN_FSV_5019:
|
||||
VAR_IN_FSV_5021:
|
||||
address: '0x427C'
|
||||
arithmetic: value / 10
|
||||
description: Economic DHW mode - Temperature of hot water Tank
|
||||
description: DHW Saving - DHW Saving Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5220,7 +5273,7 @@ VAR_IN_FSV_5021:
|
||||
VAR_IN_FSV_5023:
|
||||
address: '0x42F0'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: DHW Saving - DHW Saving Thermo on Temp.
|
||||
remarks: ''
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
@@ -5244,7 +5297,7 @@ VAR_IN_FSV_5032:
|
||||
VAR_IN_FSV_5082:
|
||||
address: '0x42DB'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: PV Control - Setting Temp. Shift Value (Cool)
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5252,7 +5305,7 @@ VAR_IN_FSV_5082:
|
||||
VAR_IN_FSV_5083:
|
||||
address: '0x42DC'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: PV Control - Setting Temp. Shift Value (Heat)
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5260,7 +5313,7 @@ VAR_IN_FSV_5083:
|
||||
VAR_IN_FSV_5092:
|
||||
address: '0x42DD'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Smart Grid Control - Setting Temp. Shift Value (Heat)
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5268,7 +5321,7 @@ VAR_IN_FSV_5092:
|
||||
VAR_IN_FSV_5093:
|
||||
address: '0x42DE'
|
||||
arithmetic: value / 10
|
||||
description: ''
|
||||
description: Smart Grid Control - Setting Temp. Shift Value (DHW)
|
||||
remarks: ''
|
||||
signed: 'false'
|
||||
type: VAR
|
||||
@@ -5793,6 +5846,15 @@ VAR_OUT_SENSOR_TOTAL_SUCTION:
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
unit: "\u00b0C"
|
||||
NASA_EHSSENTINEL_TOTAL_COP:
|
||||
address: '0x9997'
|
||||
arithmetic: ''
|
||||
description: Total COP of lifetime
|
||||
remarks: Custom Measurment
|
||||
state_class: measurement
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
unit: ''
|
||||
NASA_EHSSENTINEL_COP:
|
||||
address: '0x9998'
|
||||
arithmetic: ''
|
||||
@@ -5810,4 +5872,4 @@ NASA_EHSSENTINEL_HEAT_OUTPUT:
|
||||
state_class: measurement
|
||||
signed: 'true'
|
||||
type: VAR
|
||||
unit: "W"
|
||||
unit: "W"
|
||||
@@ -1,6 +1,10 @@
|
||||
general:
|
||||
nasaRepositoryFile: data/NasaRepository.yml
|
||||
silentMode: True
|
||||
logging:
|
||||
deviceAdded: True
|
||||
messageNotFound: False
|
||||
packetNotFromIndoorOutdoor: False
|
||||
proccessedMessage: False
|
||||
serial:
|
||||
device: /dev/ttyUSB0
|
||||
baudrate: 9600
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[50, 0, 60, 16, 0, 0, 176, 0, 255, 192, 20, 27, 13, 2, 2, 255, 255, 4, 16, 0, 0, 0, 0, 4, 27, 0, 32, 255, 255, 128, 0, 0, 128, 5, 255, 128, 23, 0, 128, 25, 0, 128, 26, 0, 128, 33, 1, 128, 50, 1, 128, 51, 2, 128, 60, 0, 128, 69, 0, 63, 195, 52]
|
||||
[50, 0, 62, 16, 0, 0, 176, 0, 255, 192, 20, 28, 16, 128, 99, 1, 128, 102, 0, 128, 119, 0, 128, 120, 2, 128, 121, 0, 128, 122, 0, 128, 123, 0, 128, 124, 0, 128, 125, 0, 128, 126, 0, 128, 127, 255, 128, 131, 0, 128, 142, 255, 128, 169, 0, 128, 175, 0, 128, 177, 0, 145, 101, 52]
|
||||
['0x32', '0x0', '0x3e', '0x10', '0x0', '0x0', '0xb0', '0x0', '0xff', '0xc0', '0x14', '0xc7', '0xc', '0x82', '0x18', '0xff', '0xdb', '0x82', '0x1a', '0xff', '0xd5', '0x82', '0x1e', '0x0', '0x8b', '0x82', '0x24', '0x0', '0xd6', '0x82', '0x25', '0x1', '0x5c', '0x82', '0x26', '0x0', '0x1b', '0x82', '0x29', '0x0', '0xe9', '0x82', '0x2e', '0x0', '0x50', '0x82', '0x31', '0x0', '0x64', '0x82', '0x34']
|
||||
['0x32', '0x0', '0x12', '0x10', '0x0', '0x0', '0xb0', '0x0', '0xff', '0xc0', '0x14', '0x5a', '0x1', '0x82', '0x1c', '0x1', '0x38', '0x1f', '0x34']
|
||||
230
helpertils/TestPacketGenerator.py
Normal file
230
helpertils/TestPacketGenerator.py
Normal file
@@ -0,0 +1,230 @@
|
||||
import json
|
||||
import NASAPacket
|
||||
import NASAMessage
|
||||
|
||||
|
||||
encode_raw = "[50, 0, 17, 16, 0, 0, 176, 0, 255, 192, 20, 143, 1, 128, 49, 0, 157, 7, 52]"
|
||||
encode_raw = "[50, 0, 60, 16, 0, 0, 176, 0, 255, 192, 20, 196, 13, 2, 2, 255, 255, 4, 16, 0, 0, 0, 0, 4, 27, 0, 32, 255, 255, 128, 0, 0, 128, 5, 255, 128, 23, 0, 128, 25, 0, 128, 26, 0, 128, 33, 1, 128, 50, 255, 128, 51, 0, 128, 60, 0, 128, 69, 0, 240, 94, 52]"
|
||||
encode_raw = "[50, 0, 56, 98, 0, 144, 178, 0, 32, 192, 17, 3, 11, 64, 147, 0, 64, 148, 0, 66, 115, 0, 0, 66, 116, 0, 0, 66, 117, 0, 0, 66, 118, 0, 0, 66, 119, 0, 0, 66, 120, 0, 0, 66, 121, 0, 0, 66, 122, 0, 0, 66, 123, 0, 0, 221, 200, 52]"
|
||||
encode_raw = "[50, 0, 56, 98, 0, 144, 178, 0, 32, 192, 17, 240, 11, 64, 147, 0, 64, 148, 0, 66, 115, 0, 0, 66, 116, 0, 0, 66, 117, 0, 0, 66, 118, 0, 0, 66, 119, 0, 0, 66, 120, 0, 0, 66, 121, 0, 0, 66, 122, 0, 0, 66, 123, 0, 0, 76, 33, 52]"
|
||||
#encode_raw ="[50, 0, 48, 98, 0, 144, 178, 0, 32, 192, 17, 240, 11, 64, 147, 0, 64, 148, 0, 66, 115, 0, 0, 66, 116, 0, 66, 117, 0, 66, 118, 0, 66, 119, 0, 66, 120, 0, 66, 121, 0, 66, 122, 0, 66, 123, 0, 7, 180, 52]"
|
||||
try:
|
||||
encode_bytearray = json.loads(encode_raw.strip()) # for [12, 234, 456 ,67]
|
||||
except:
|
||||
encode_tmp = encode_raw.strip().replace("'", "").replace("[", "").replace("]", "").split(", ") # for ['0x1', '0x2' ..]
|
||||
encode_bytearray = [int(value, 16) for value in encode_tmp]
|
||||
|
||||
|
||||
print(f"encode raw: {bytearray(encode_bytearray)}")
|
||||
print(f"encode bytearray: {encode_bytearray}")
|
||||
print(f"encode bytearray length: {len(encode_bytearray)}")
|
||||
|
||||
encoded_nasa = NASAPacket.NASAPacket()
|
||||
encoded_nasa.parse(encode_bytearray)
|
||||
|
||||
print(f"encode NASA Object: {encoded_nasa}")
|
||||
|
||||
# time to reverse that thing!
|
||||
decoded_nasa = NASAPacket.NASAPacket()
|
||||
decoded_nasa.set_packet_source_address_class(NASAPacket.AddressClassEnum.Outdoor)
|
||||
decoded_nasa.set_packet_source_channel(0)
|
||||
decoded_nasa.set_packet_source_address(0)
|
||||
decoded_nasa.set_packet_dest_address_class(NASAPacket.AddressClassEnum.BroadcastSelfLayer)
|
||||
decoded_nasa.set_packet_dest_channel(0)
|
||||
decoded_nasa.set_packet_dest_address(255)
|
||||
decoded_nasa.set_packet_information(True)
|
||||
decoded_nasa.set_packet_version(2)
|
||||
decoded_nasa.set_packet_retry_count(0)
|
||||
decoded_nasa.set_packet_type(NASAPacket.PacketType.Normal)
|
||||
decoded_nasa.set_packet_data_type(NASAPacket.DataType.Notification)
|
||||
decoded_nasa.set_packet_number(143)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8031)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
decoded_nasa.set_packet_messages([tmp_msg])
|
||||
|
||||
decoded_nasa = NASAPacket.NASAPacket()
|
||||
decoded_nasa.set_packet_source_address_class(NASAPacket.AddressClassEnum.Outdoor)
|
||||
decoded_nasa.set_packet_source_channel(0)
|
||||
decoded_nasa.set_packet_source_address(0)
|
||||
decoded_nasa.set_packet_dest_address_class(NASAPacket.AddressClassEnum.BroadcastSelfLayer)
|
||||
decoded_nasa.set_packet_dest_channel(0)
|
||||
decoded_nasa.set_packet_dest_address(255)
|
||||
decoded_nasa.set_packet_information(True)
|
||||
decoded_nasa.set_packet_version(2)
|
||||
decoded_nasa.set_packet_retry_count(0)
|
||||
decoded_nasa.set_packet_type(NASAPacket.PacketType.Normal)
|
||||
decoded_nasa.set_packet_data_type(NASAPacket.DataType.Notification)
|
||||
decoded_nasa.set_packet_number(196)
|
||||
lst = []
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x0202)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([255, 255])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x0410)
|
||||
tmp_msg.set_packet_message_type(2)
|
||||
tmp_msg.set_packet_payload([0, 0, 0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x41b)
|
||||
tmp_msg.set_packet_message_type(2)
|
||||
tmp_msg.set_packet_payload([0, 32, 255, 255])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8000)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8005)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([255])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8017)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8019)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x801a)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8021)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([1])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8032)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([255])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8033)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x803c)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x8045)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
decoded_nasa.set_packet_messages(lst)
|
||||
|
||||
#rasw = decoded_nasa.to_raw()
|
||||
|
||||
decoded_nasa = NASAPacket.NASAPacket()
|
||||
decoded_nasa.set_packet_source_address_class(NASAPacket.AddressClassEnum.WiFiKit)
|
||||
decoded_nasa.set_packet_source_channel(0)
|
||||
decoded_nasa.set_packet_source_address(144)
|
||||
decoded_nasa.set_packet_dest_address_class(NASAPacket.AddressClassEnum.BroadcastSetLayer)
|
||||
decoded_nasa.set_packet_dest_channel(0)
|
||||
decoded_nasa.set_packet_dest_address(32)
|
||||
decoded_nasa.set_packet_information(True)
|
||||
decoded_nasa.set_packet_version(2)
|
||||
decoded_nasa.set_packet_retry_count(0)
|
||||
decoded_nasa.set_packet_type(NASAPacket.PacketType.Normal)
|
||||
decoded_nasa.set_packet_data_type(NASAPacket.DataType.Read)
|
||||
decoded_nasa.set_packet_number(240)
|
||||
lst = []
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4093)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4094)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4273)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4274)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4275)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4276)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4277)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4278)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4279)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x427a)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x427b)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
decoded_nasa.set_packet_messages(lst)
|
||||
|
||||
decoded_nasa = NASAPacket.NASAPacket()
|
||||
decoded_nasa.set_packet_source_address_class(NASAPacket.AddressClassEnum.WiFiKit)
|
||||
decoded_nasa.set_packet_source_channel(0)
|
||||
decoded_nasa.set_packet_source_address(144)
|
||||
decoded_nasa.set_packet_dest_address_class(NASAPacket.AddressClassEnum.BroadcastSelfLayer)
|
||||
decoded_nasa.set_packet_dest_channel(255)
|
||||
decoded_nasa.set_packet_dest_address(255)
|
||||
decoded_nasa.set_packet_information(True)
|
||||
decoded_nasa.set_packet_version(2)
|
||||
decoded_nasa.set_packet_retry_count(0)
|
||||
decoded_nasa.set_packet_type(NASAPacket.PacketType.Normal)
|
||||
decoded_nasa.set_packet_data_type(NASAPacket.DataType.Notification)
|
||||
decoded_nasa.set_packet_number(168)
|
||||
tmp_msg = NASAMessage.NASAMessage()
|
||||
tmp_msg.set_packet_message(0x0000)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([2])
|
||||
decoded_nasa.set_packet_messages([tmp_msg])
|
||||
|
||||
|
||||
rasw = decoded_nasa.to_raw()
|
||||
|
||||
print(f"decoded bytearray: {rasw}")
|
||||
print(f"decoded NASA Object: {decoded_nasa}")
|
||||
print(f"decoded bytearray: {[int(value) for value in rasw]}")
|
||||
|
||||
print("Reverse Check:")
|
||||
checkback = NASAPacket.NASAPacket()
|
||||
checkback.parse(rasw)
|
||||
print(checkback)
|
||||
@@ -5,7 +5,7 @@ import traceback
|
||||
from MessageProcessor import MessageProcessor
|
||||
from EHSArguments import EHSArguments
|
||||
from EHSConfig import EHSConfig
|
||||
from EHSExceptions import MessageWarningException, MessageCapacityStructureWarning
|
||||
from EHSExceptions import MessageWarningException, SkipInvalidPacketException
|
||||
from MQTTClient import MQTTClient
|
||||
import aiofiles
|
||||
import json
|
||||
@@ -13,10 +13,11 @@ import struct
|
||||
import binascii
|
||||
|
||||
# Get the logger
|
||||
from CustomLogger import logger, setSilent
|
||||
from NASAPacket import NASAPacket
|
||||
from CustomLogger import logger
|
||||
from NASAPacket import NASAPacket, AddressClassEnum, PacketType, DataType
|
||||
from NASAMessage import NASAMessage
|
||||
|
||||
version = "0.1.0 Stable"
|
||||
version = "0.2.0 Stable"
|
||||
|
||||
async def main():
|
||||
"""
|
||||
@@ -26,9 +27,8 @@ async def main():
|
||||
2. Reads command-line arguments.
|
||||
3. Reads configuration settings.
|
||||
4. Connects to the MQTT broker.
|
||||
5. Sets silent mode if specified in the configuration.
|
||||
6. If dry run mode is enabled, reads data from a dump file and processes it.
|
||||
7. If not in dry run mode, reads data from a serial port and processes it.
|
||||
5. If dry run mode is enabled, reads data from a dump file and processes it.
|
||||
6. If not in dry run mode, reads data from a serial port and processes it.
|
||||
Args:
|
||||
None
|
||||
Returns:
|
||||
@@ -61,10 +61,6 @@ async def main():
|
||||
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# if Silent is true, set Silent Mode
|
||||
if config.GENERAL['silentMode']:
|
||||
setSilent()
|
||||
|
||||
# if dryrun then we read from dumpfile
|
||||
if args.DRYRUN:
|
||||
logger.info(f"DRYRUN detected, reading from dumpfile {args.DUMPFILE}")
|
||||
@@ -75,12 +71,12 @@ async def main():
|
||||
except:
|
||||
line = line.strip().replace("'", "").replace("[", "").replace("]", "").split(", ") # for ['0x1', '0x2' ..]
|
||||
line = [int(value, 16) for value in line]
|
||||
await process_packet(line, args)
|
||||
await process_packet(line, args, config)
|
||||
else:
|
||||
# we are not in dryrun mode, so we need to read from Serial Pimort
|
||||
await serial_read(config, args)
|
||||
await serial_connection(config, args)
|
||||
|
||||
async def process_buffer(buffer, args):
|
||||
async def process_buffer(buffer, args, config):
|
||||
"""
|
||||
Processes a buffer of data asynchronously, identifying and handling packets based on specific criteria.
|
||||
Args:
|
||||
@@ -108,14 +104,14 @@ async def process_buffer(buffer, args):
|
||||
for i in range(0, len(buffer)):
|
||||
if buffer[i] == 0x32:
|
||||
if (len(buffer[i:]) > 14):
|
||||
asyncio.create_task(process_packet(buffer[i:], args))
|
||||
asyncio.create_task(process_packet(buffer[i:], args, config))
|
||||
else:
|
||||
logger.debug(f"Buffermessages to short for NASA {len(buffer)}")
|
||||
break
|
||||
else:
|
||||
logger.debug(f"Buffer to short for NASA {len(buffer)}")
|
||||
|
||||
async def serial_read(config, args):
|
||||
async def serial_connection(config, args):
|
||||
"""
|
||||
Asynchronously reads data from a serial connection and processes it.
|
||||
Args:
|
||||
@@ -147,25 +143,28 @@ async def serial_read(config, args):
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
bytesize=serial.EIGHTBITS,
|
||||
rtscts=True,
|
||||
timeout=0
|
||||
timeout=1
|
||||
)
|
||||
|
||||
# start the async buffer process
|
||||
#asyncio.create_task(process_buffer(buffer, args))# start the async buffer process
|
||||
|
||||
# TODO have to be tested and verified, please do not try it yet
|
||||
# start the async writer process
|
||||
#asyncio.create_task(serial_write(writer, reader))
|
||||
await asyncio.gather(
|
||||
serial_read(reader, args, config),
|
||||
#serial_write(writer, reader, args),
|
||||
)
|
||||
|
||||
# Read loop
|
||||
|
||||
async def serial_read(reader, args, config):
|
||||
while True:
|
||||
data = await reader.readuntil(b'\x34') # Read up to end of next message 0x34
|
||||
if data:
|
||||
asyncio.create_task(process_buffer(data, args))
|
||||
asyncio.create_task(process_buffer(data, args, config))
|
||||
#buffer.extend(data)
|
||||
logger.debug(f"Received: {data}")
|
||||
logger.debug(f"Received: {data!r}")
|
||||
logger.debug(f"Received: {[hex(x) for x in data]}")
|
||||
|
||||
async def serial_write(writer, reader):
|
||||
await asyncio.sleep(0.1) # Yield control to other tasks
|
||||
|
||||
async def serial_write(writer:asyncio.StreamWriter, reader: asyncio.StreamReader, args):
|
||||
"""
|
||||
|
||||
TODO Not used yet, only for future use...
|
||||
@@ -183,36 +182,85 @@ async def serial_write(writer, reader):
|
||||
await asyncio.sleep(5)
|
||||
# Example data to write
|
||||
|
||||
packet = bytearray([
|
||||
#0x32, # Packet Start Byte
|
||||
#0x00, 0x12, # Packet Size
|
||||
0x80, # Source Address Class JIGTester
|
||||
0xFF, # Source Channel
|
||||
0x00, # Source Address
|
||||
0x20, # Destination Address Class Indoor
|
||||
0x00, # Destination Channel
|
||||
0x00, # Destination Address
|
||||
0xC0, # Packet Information + Protocol Version + Retry Count
|
||||
0x11, # Packet Type [Normal = 1] + Data Type [Read = 1]
|
||||
0xF0, # Packet Number
|
||||
0x01, # Capacity (Number of Messages)
|
||||
0x42, 0x56, # NASA Message Number
|
||||
0x00, 0x00 # Message Payload (placeholder for return value)
|
||||
])
|
||||
|
||||
crc=binascii.crc_hqx(packet, 0)
|
||||
# NOTE: include length of CRC(2) and length of length field(2) in the
|
||||
# total length, exclude SF/TF of total length
|
||||
final_packet = struct.pack(">BH", 0x32, len(packet)+2+2) + packet + struct.pack(">HB", crc, 0x34)
|
||||
# ['0x32', '0x0', '0x12', '0x80', '0xff', '0x0', '0x20', '0x0', '0x0', '0xc0', '0x11', '0xf0', '0x1', '0x42', '0x56', '0x0', '0x0', '0xf9', '0x65', '0x34']
|
||||
# ['0x32', '0x0', '0x12', '0x80', '0xff', '0x0', '0x20', '0x0', '0x0', '0xc0', '0x11', '0xf0', '0x1', '0x42', '0x56', '0x0', '0x0', '0x38', '0xc6', '0x34']
|
||||
decoded_nasa = NASAPacket()
|
||||
decoded_nasa.set_packet_source_address_class(AddressClassEnum.WiFiKit)
|
||||
decoded_nasa.set_packet_source_channel(0)
|
||||
decoded_nasa.set_packet_source_address(144)
|
||||
decoded_nasa.set_packet_dest_address_class(AddressClassEnum.BroadcastSetLayer)
|
||||
decoded_nasa.set_packet_dest_channel(0)
|
||||
decoded_nasa.set_packet_dest_address(32)
|
||||
decoded_nasa.set_packet_information(True)
|
||||
decoded_nasa.set_packet_version(2)
|
||||
decoded_nasa.set_packet_retry_count(0)
|
||||
decoded_nasa.set_packet_type(PacketType.Normal)
|
||||
decoded_nasa.set_packet_data_type(DataType.Read)
|
||||
decoded_nasa.set_packet_number(3)
|
||||
lst = []
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4093)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4094)
|
||||
tmp_msg.set_packet_message_type(0)
|
||||
tmp_msg.set_packet_payload([0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4273)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4274)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4275)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4276)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4277)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4278)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x4279)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x427a)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
tmp_msg = NASAMessage()
|
||||
tmp_msg.set_packet_message(0x427b)
|
||||
tmp_msg.set_packet_message_type(1)
|
||||
tmp_msg.set_packet_payload([0, 0])
|
||||
lst.append(tmp_msg)
|
||||
decoded_nasa.set_packet_messages(lst)
|
||||
final_packet = decoded_nasa.to_raw()
|
||||
writer.write(final_packet)
|
||||
await writer.drain()
|
||||
logger.debug(f"Sent data raw: {final_packet}")
|
||||
logger.debug(f"Sent data raw: {[hex(x) for x in final_packet]}")
|
||||
await asyncio.sleep(1) # Adjust the interval as needed
|
||||
logger.info(f"Sent data raw: {final_packet}")
|
||||
logger.info(f"Sent data raw: {decoded_nasa}")
|
||||
logger.info(f"Sent data raw: {[hex(x) for x in final_packet]}")
|
||||
logger.info(f"Sent data raw: {[x for x in final_packet]}")
|
||||
|
||||
async def process_packet(buffer, args):
|
||||
async def process_packet(buffer, args, config):
|
||||
"""
|
||||
Asynchronously processes a packet buffer.
|
||||
If `dumpWriter` is `None`, it attempts to process the packet using `MessageProcessor`.
|
||||
@@ -233,13 +281,29 @@ async def process_packet(buffer, args):
|
||||
logger.debug("Packet processed: ")
|
||||
logger.debug(f"Packet raw: {[hex(x) for x in buffer]}")
|
||||
logger.debug(nasa_packet)
|
||||
messageProcessor = MessageProcessor()
|
||||
messageProcessor.process_message(nasa_packet)
|
||||
if nasa_packet.packet_source_address_class in (AddressClassEnum.Outdoor, AddressClassEnum.Indoor):
|
||||
messageProcessor = MessageProcessor()
|
||||
messageProcessor.process_message(nasa_packet)
|
||||
elif nasa_packet.packet_source_address_class == AddressClassEnum.WiFiKit and \
|
||||
nasa_packet.packet_dest_address_class == AddressClassEnum.BroadcastSelfLayer and \
|
||||
nasa_packet.packet_data_type == DataType.Notification:
|
||||
pass
|
||||
else:
|
||||
if config.LOGGING['packetNotFromIndoorOutdoor']:
|
||||
logger.info("Message not From Indoor or Outdoor")
|
||||
logger.info(nasa_packet)
|
||||
logger.info(f"Packet int: {[x for x in buffer]}")
|
||||
logger.info(f"Packet hex: {[hex(x) for x in buffer]}")
|
||||
else:
|
||||
logger.debug("Message not From Indoor or Outdoor")
|
||||
logger.debug(nasa_packet)
|
||||
logger.debug(f"Packet int: {[x for x in buffer]}")
|
||||
logger.debug(f"Packet hex: {[hex(x) for x in buffer]}")
|
||||
except ValueError as e:
|
||||
logger.warning("Value Error on parsing Packet, Packet will be skipped")
|
||||
logger.warning(f"Error processing message: {e}")
|
||||
logger.warning(f"Complete Packet: {[hex(x) for x in buffer]}")
|
||||
except MessageCapacityStructureWarning as e:
|
||||
except SkipInvalidPacketException as e:
|
||||
logger.debug("Warnung accured, Packet will be skipped")
|
||||
logger.debug(f"Error processing message: {e}")
|
||||
logger.debug(f"Complete Packet: {[hex(x) for x in buffer]}")
|
||||
|
||||
Reference in New Issue
Block a user