Skip to content

Commit

Permalink
Merge pull request #12 from grimmpp/feature-branch
Browse files Browse the repository at this point in the history
Feature branch
  • Loading branch information
grimmpp authored Feb 22, 2024
2 parents 5e48543 + 90a6c56 commit 267294e
Show file tree
Hide file tree
Showing 35 changed files with 741 additions and 249 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Furthermore, it automatically can detect default settings for Home Assistant con
(The exported Home Assistant configuration is intended for the [Eltako Home Assistant Integration](https://github.com/grimmpp/home-assistant-eltako/))

## Preview
<img src="https://github.com/grimmpp/enocean-device-manager/blob/main/screenshot.png" />
<img src="https://github.com/grimmpp/enocean-device-manager/blob/main/screenshot2.png" />
What you can see here can automatically detected by reading the memory of the bus devices via FAM14. Telegrams of sensors and decentralized devices will be received and additionally added.
Additional info for Home Assistant is automatically added. The configuration for Home Assistant can be generated by the detected information.
For further steps it is planned to extend the support for changing the data which was collected so that a proper management of the devices can be supported.
Expand Down
7 changes: 7 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change Log

## v0.1.9 Read Support for USB300 + Multi-Gateway Support for HA Config Export
* Fixed compatibility of loading old application configs
* Icons added
* Remove Smart Home addresses as real buttons from HA export
* Serial port detection for FAM-USB and USB300 improved.
* TODO: Cleanup of ESP3 communication, move function into lib

## v0.1.8 Wireless Tranceiver Support
* Reset suggested HA settings added
* Support for FAM-USB. Is now detected as gateway and contained in HA config
Expand Down
28 changes: 27 additions & 1 deletion demo.eodm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
!!python/object:eo_man.data.application_data.ApplicationData
application_version: 0.1.5
application_version: 0.1.7
data_filters:
Buttons: !!python/object:eo_man.data.filter.DataFilter
device_address_filter: []
Expand Down Expand Up @@ -154,6 +154,19 @@ devices:
name: HA Contoller FF-86-B0-8C
use_in_ha: false
version: unknown
FF-BC-00-00: !!python/object:eo_man.data.device.Device
address: FF-BC-00-00
base_id: FF-BC-00-00
bus_device: false
channel: 1
comment: null
dev_size: 1
device_type: FAM-USB (Wireless Tranceiver)
external_id: FF-BC-00-00
memory_entries: &id003 []
name: FAM-USB (FF-BC-00-00)
use_in_ha: true
version: null
FF-CD-60-80: !!python/object:eo_man.data.device.Device
additional_fields: {}
address: 00-00-00-FF
Expand Down Expand Up @@ -710,6 +723,19 @@ devices:
name: HA Contoller 00-00-B0-07
use_in_ha: false
version: unknown
FF-D6-00-00: !!python/object:eo_man.data.device.Device
address: FF-D6-00-00
base_id: FF-D6-00-00
bus_device: false
channel: 1
comment: null
dev_size: 1
device_type: USB300 (Wireless Tranceiver)
external_id: FF-D6-00-00
memory_entries: *id003
name: USB300 (FF-D6-00-00)
use_in_ha: true
version: null
FF-E2-35-90: !!python/object:eo_man.data.device.Device
address: FF-E2-35-90
base_id: 00-00-00-00
Expand Down
4 changes: 1 addition & 3 deletions eo_man/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from .controller.app_bus import AppBus, AppBusEventType

import logging
from tkinter import *


def cli_argument():
Expand Down Expand Up @@ -78,8 +77,7 @@ def main():
if opts.app_config and opts.app_config.endswith('.eodm') and opts.ha_config:
HomeAssistantConfigurationGenerator(app_bus, data_manager).save_as_yaml_to_file(opts.ha_config)
else:
root = Tk()
MainPanel(root, app_bus, data_manager)
MainPanel(app_bus, data_manager)

if __name__ == "__main__":
main()
154 changes: 118 additions & 36 deletions eo_man/controller/esp3_serial_com.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,18 @@
class ESP3SerialCommunicator(Communicator):
''' Serial port communicator class for EnOcean radio '''

def __init__(self, filename, log=None, callback=None, baud_rate=57600, reconnection_timeout:float=10, esp2_translation_enabled:bool=False):
def __init__(self,
filename,
log=None,
callback=None,
baud_rate=57600,
reconnection_timeout:float=10,
esp2_translation_enabled:bool=False,
auto_reconnect:bool=True):

self.esp2_translation_enabled = esp2_translation_enabled
self._outside_callback = callback
self._auto_reconnect = auto_reconnect
super(ESP3SerialCommunicator, self).__init__(self.__callback_wrapper)

self._filename = filename
Expand Down Expand Up @@ -50,49 +59,36 @@ def _fire_status_change_handler(self, connected:bool) -> None:
except Exception as e:
pass

async def base_exchange(self, request:ESP2Message):
self.esp2_translation_enabled = True
self.send(request)

@classmethod
def convert_esp2_to_esp3_message(cls, message: ESP2Message) -> RadioPacket:

d = message.data[0]

optional = []
if isinstance(message, RPSMessage):
org = RORG.RPS
org_func = 0x02
org_type = 0x02
data = [message.data[0]]
elif isinstance(message, Regular1BSMessage):
org = RORG.BS1
org_func = 0x02
org_type = 0x02
data = [message.data[0]]
elif isinstance(message, Regular4BSMessage):
org = RORG.BS4
org_func = 0x01
org_type = 0x01
d = message.data
telegram_count = 0x03
optional = [telegram_count, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
data = message.data
else:
return None

# command = [0xA5, 0x02, bval, 0x01, 0x09]
# command.extend(self._sender_id)
# command.extend([0x00])
# self.send_command(data=command, optional=[], packet_type=0x01)

# data = bytes([org, 0x02, 0x01, 0x01, 0x09]) + d + message.address + bytes([message.status])

# RadioPacket.create(rorg=RORG.BS4, rorg_func=0x20, rorg_type=0x01,
# sender=transmitter_id,
# CV=50,
# TMP=21.5,
# ES='true')
sender = [x for x in message.address]

# packet = Packet(packet_type=0x01, data=data, optional=[])
packet = RadioPacket.create(rorg=org,
rorg_func=org_func,
rorg_type=org_type,
sender=sender,
command=[0x01, 0x00, 0x00, 0x09]
)
return packet
command=[org]
command.extend(data)
command.extend(sender)
command.extend([message.status])

return Packet(PACKET.RADIO, command, optional)

@classmethod
def convert_esp3_to_esp2_message(cls, packet: RadioPacket) -> ESP2Message:
Expand Down Expand Up @@ -174,10 +170,16 @@ def run(self):
self.is_serial_connected.clear()
self.log.error(e)
self.__ser = None
self.log.info("Serial communication crashed. Wait %s seconds for reconnection.", self.__recon_time)
time.sleep(self.__recon_time)
if self._auto_reconnect:
self.log.info("Serial communication crashed. Wait %s seconds for reconnection.", self.__recon_time)
time.sleep(self.__recon_time)
else:
self._stop_flag.set()

self.__ser.close()
if self.__ser is not None:
self.__ser.close()
self.__ser = None
self.is_serial_connected.clear()
self._fire_status_change_handler(connected=False)
self.logger.info('SerialCommunicator stopped')

Expand Down Expand Up @@ -219,7 +221,7 @@ def base_id(self):
# Unfortunately, all other messages received during this time are ignored.
for i in range(0, 10):
try:
packet = self.receive.get(block=True, timeout=0.2)
packet = self.receive.get(block=True, timeout=0.1)
# We're only interested in responses to the request in question.
if packet.packet_type == PACKET.RESPONSE and packet.response == RETURN_CODE.OK and len(packet.response_data) == 4: # noqa: E501
# Base ID is set in the response data.
Expand All @@ -233,7 +235,7 @@ def base_id(self):
continue
# Return the current Base ID (might be None).
return self._base_id

if __name__ == '__main__':

def cb(package:Packet):
Expand All @@ -246,7 +248,36 @@ def cb(package:Packet):
# asyncio.run( com.send(Packet(PACKET.COMMON_COMMAND, data=[0x08])) )


com = ESP3SerialCommunicator("COM12", callback=cb)
# ser = serial.Serial("COM12", 57600, timeout=0.1)

# # org = 0xF6 # org = 0x05, rorg = 0xF6
# # package_type = 0x01 # Radio_ERP_1
# # telegram_count = 0x02 # Sub-Telegram Count
# # header_checksum = 0x7A
# # h_seq = property(lambda self: 3 if self.outgoing else 0)
# # data = [0x70]
# # address = [0xFF,0xD6,0x30,0x01]
# # status = 0x00

# # # 55 00 07 07 01 7A F6 70 FF B9 FC 8D 30 02 FF FF FF FF 44 00 F8
# # body = bytes((0x07, 0x07, package_type, header_checksum, org, *data, *address, status, telegram_count, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))

# # data = b"\x55\x00" + body
# # msg = data + crc8.crc8(data[1:]).digest()

# msg = MY_RPSMessage(b'\xFF\xD6\x30\x01',0x00, b'\x70', True)

# ser.write(msg.serialize())
# ser.read_all()

# print("\n\n")
# time.sleep(2)

# ser.close()

# exit(0)

com = ESP3SerialCommunicator("COM12", callback=cb, esp2_translation_enabled=False)
com.start()
com.is_serial_connected.wait(timeout=10)
com.set_callback(None)
Expand All @@ -257,9 +288,60 @@ def cb(package:Packet):
com.set_callback(cb)
com.base_id

# asyncio.run( com.send(RPSMessage(address=b'\xFF\xD6\x30\x01', status=b'\x30', data=b'\x50', outgoing=True)) )
command=[RORG.BS4, 0x01, 0x00, 0x00, 0x09]
command.extend([0xFF,0xD6,0x30, 0x01])
command.extend([0x00])

# asyncio.run( com.send(Packet(0x01, command, optional=[])) )


sender = [0xFF,0xD6,0x30,0x01]
status = [0x30]

command=[RORG.RPS, 0x30]
command.extend(sender)
command.extend(status)

destination = [0xFF,0xFF,0xFF,0xFF]# [0xFF,0xA2,0x24,0x01]


# command.extend([0xFF,0xD6,0x30,0x01])
# command.extend([0x00])

# p = RadioPacket.create(RORG.RPS, rorg_func=0x02, rorg_type=0x02, command=command, destination=destination, sender=sender)
# p = Packet(packet_type = 0x01, data=command)
# p.status = 0x30
# p.data[1] = 0x30
# p.data[6] = 0x30

p = ESP3SerialCommunicator.convert_esp2_to_esp3_message(RPSMessage(b'\xFF\xD6\x30\x01', 0x30, b'\x30', True))


# p = ESP3SerialCommunicator.convert_esp2_to_esp3_message(Regular4BSMessage(b'\xFF\xD6\x30\x01', 0x00, b'\x01\x00\x00\x09', True))
asyncio.run( com.send(p) )

print("\n\n")
# time.sleep(3)


p = ESP3SerialCommunicator.convert_esp2_to_esp3_message(Regular4BSMessage(b'\xFF\xD6\x30\x01', 0x00, bytes((0x01, 0x00, 0x00, 0x09)), True))
print(', '.join([hex(i) for i in p.build()]))

# p = ESP3SerialCommunicator.convert_esp2_to_esp3_message(RPSMessage(b'\xFF\xD6\x30\x01', 0x30, b'\x10', True))
# p = ESP3SerialCommunicator.convert_esp2_to_esp3_message(Regular4BSMessage(b'\xFF\x82\x3E\x70', 0x00, bytes((0x01, 0x00, 0x00, 0x08)), True))
print(p)
asyncio.run( com.send(p) )


print("\n\n")
time.sleep(2)



com.stop()
exit(0)

data = [0xf6, 0x50, 0xff, 0xa2, 0x24, 0x1, 0x30]
body:bytes = bytes([0x0b, 0x05] + data[1:2] + [0,0,0] + data[2:])
msg = prettify( ESP2Message(body) )
Expand Down
Loading

0 comments on commit 267294e

Please sign in to comment.