Compare commits
6 commits
82ee08a1d7
...
140acba1f5
Author | SHA1 | Date | |
---|---|---|---|
140acba1f5 | |||
3a8fd634c5 | |||
80bfd414ec | |||
1ccea2bf9c | |||
7ab0b1ce62 | |||
fa9d5d73c4 |
11 changed files with 125 additions and 13 deletions
|
@ -2,7 +2,7 @@
|
||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.0.1
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
|
@ -23,7 +23,7 @@ repos:
|
||||||
- id: detect-private-key
|
- id: detect-private-key
|
||||||
|
|
||||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
||||||
rev: 2.3.54
|
rev: 2.7.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: editorconfig-checker
|
- id: editorconfig-checker
|
||||||
args:
|
args:
|
||||||
|
@ -35,16 +35,19 @@ repos:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.910-1
|
rev: v1.2.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
|
args:
|
||||||
|
- "--install-types"
|
||||||
|
- "--non-interactive"
|
||||||
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 21.10b0
|
rev: 23.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.9.3
|
rev: 5.12.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Connector
|
# Connector
|
||||||
|
|
||||||
The connector is a RJ12 (6P6C, phone connector with all 6 positions populated)
|
The connector is a RJ12 (6P6C, phone connector with all 6 positions populated).
|
||||||
The interface uses RS-232 levels (±15V)
|
The interface uses RS-232 levels (±5V), make sure your adaptor can handle this! (Some adaptors require higher voltages).
|
||||||
|
TODO: Triple check RS-232 voltages.
|
||||||
|
|
||||||
## Pinout
|
## Pinout
|
||||||
|
|
||||||
|
|
12
config-example.yaml
Normal file
12
config-example.yaml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
consumers:
|
||||||
|
stdio.StdoutConsumer: {}
|
||||||
|
interface:
|
||||||
|
name: serial.SerialInterface
|
||||||
|
params:
|
||||||
|
port: /dev/ttyUSB0
|
||||||
|
baudrate: 9600
|
||||||
|
timeout: 2
|
||||||
|
# name: feasycom.FeasycomInterface
|
||||||
|
# params:
|
||||||
|
# mac: DC:0D:30:9C:61:BA
|
||||||
|
# timeout: 5
|
29
misc/test_serial.py
Normal file
29
misc/test_serial.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
from serial import Serial
|
||||||
|
|
||||||
|
print(sys.path)
|
||||||
|
sys.path.insert(1, os.path.dirname(os.path.dirname(sys.argv[0])))
|
||||||
|
# from srnemqtt.constants import MAC
|
||||||
|
# from srnemqtt.lib.feasycom_ble import BTLEUart
|
||||||
|
from srnemqtt.protocol import construct_request, write # noqa: E402
|
||||||
|
|
||||||
|
for rate in [1200, 2400, 4800, 9600, 115200]:
|
||||||
|
print(rate)
|
||||||
|
with Serial("/dev/ttyUSB0", baudrate=rate, timeout=2) as x:
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
print(x)
|
||||||
|
|
||||||
|
write(x, construct_request(0x0E, words=3))
|
||||||
|
print(x.read(3))
|
||||||
|
print(x.read(6))
|
||||||
|
print(x.read(2))
|
||||||
|
|
||||||
|
# x.timeout = 2
|
||||||
|
|
||||||
|
# print(x.read())
|
||||||
|
# print(x.read(1))
|
7
misc/test_serial_loopback.py
Normal file
7
misc/test_serial_loopback.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from serial import Serial
|
||||||
|
|
||||||
|
with Serial("/dev/ttyUSB0", baudrate=9600, timeout=2) as x:
|
||||||
|
x.write(b"Hello, World!")
|
||||||
|
print(x.read(13))
|
||||||
|
print(x.read(13))
|
|
@ -3,3 +3,6 @@ rrdtool
|
||||||
bluepy
|
bluepy
|
||||||
libscrc
|
libscrc
|
||||||
paho-mqtt
|
paho-mqtt
|
||||||
|
pyserial
|
||||||
|
|
||||||
|
types-PyYAML
|
||||||
|
|
|
@ -5,28 +5,34 @@ import time
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from bluepy import btle
|
from bluepy.btle import BTLEDisconnectError
|
||||||
|
from serial import SerialException
|
||||||
|
|
||||||
from .config import get_config, get_consumers
|
from .config import get_config, get_consumers, get_interface
|
||||||
from .constants import MAC
|
|
||||||
from .lib.feasycom_ble import BTLEUart
|
|
||||||
from .protocol import parse_battery_state, parse_historical_entry, try_read_parse
|
from .protocol import parse_battery_state, parse_historical_entry, try_read_parse
|
||||||
from .solar_types import DataName
|
from .solar_types import DataName
|
||||||
from .util import Periodical, log
|
from .util import Periodical, log
|
||||||
|
|
||||||
|
|
||||||
|
class CommunicationError(BTLEDisconnectError, SerialException, IOError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
conf = get_config()
|
conf = get_config()
|
||||||
consumers = get_consumers(conf)
|
consumers = get_consumers(conf)
|
||||||
|
|
||||||
per_voltages = Periodical(interval=15)
|
per_voltages = Periodical(interval=15)
|
||||||
per_current_hist = Periodical(interval=60)
|
per_current_hist = Periodical(interval=60)
|
||||||
|
# import serial
|
||||||
|
|
||||||
|
# ser = serial.Serial()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
log("Connecting...")
|
log("Connecting...")
|
||||||
with BTLEUart(MAC, timeout=5) as dev:
|
with get_interface() as dev:
|
||||||
log("Connected.")
|
log("Connected.")
|
||||||
|
|
||||||
# write(dev, construct_request(0, 32))
|
# write(dev, construct_request(0, 32))
|
||||||
|
@ -96,7 +102,7 @@ def main():
|
||||||
# else:
|
# else:
|
||||||
# write(wd, CMD_ENABLE_LOAD)
|
# write(wd, CMD_ENABLE_LOAD)
|
||||||
|
|
||||||
except btle.BTLEDisconnectError:
|
except CommunicationError:
|
||||||
log("ERROR: Disconnected")
|
log("ERROR: Disconnected")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ from typing import Any, Dict, List, Optional, Type
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from srnemqtt.interfaces import BaseInterface
|
||||||
|
|
||||||
from .consumers import BaseConsumer
|
from .consumers import BaseConsumer
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,6 +54,30 @@ def get_consumers(conf: Optional[Dict[str, Any]] = None) -> List[BaseConsumer]:
|
||||||
return consumers
|
return consumers
|
||||||
|
|
||||||
|
|
||||||
|
def _get_interface(name: str) -> Type[BaseInterface]:
|
||||||
|
mod_name, cls_name = name.rsplit(".", 1)
|
||||||
|
|
||||||
|
mod = importlib.import_module(f".interfaces.{mod_name}", package=__package__)
|
||||||
|
|
||||||
|
res = getattr(mod, cls_name)
|
||||||
|
assert issubclass(res, BaseInterface)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_interface(conf: Optional[Dict[str, Any]] = None) -> BaseInterface:
|
||||||
|
if conf is None:
|
||||||
|
conf = get_config()
|
||||||
|
|
||||||
|
name = conf["interface"]["name"]
|
||||||
|
params = conf["interface"].get("params", {})
|
||||||
|
|
||||||
|
mod = _get_interface(name)
|
||||||
|
assert mod
|
||||||
|
|
||||||
|
return mod(**params)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
conf = get_config()
|
conf = get_config()
|
||||||
|
|
||||||
|
|
7
srnemqtt/interfaces/__init__.py
Normal file
7
srnemqtt/interfaces/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from abc import ABCMeta
|
||||||
|
from io import RawIOBase
|
||||||
|
|
||||||
|
|
||||||
|
class BaseInterface(RawIOBase, metaclass=ABCMeta):
|
||||||
|
pass
|
10
srnemqtt/interfaces/feasycom.py
Normal file
10
srnemqtt/interfaces/feasycom.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from ..lib.feasycom_ble import BTLEUart
|
||||||
|
from . import BaseInterface
|
||||||
|
|
||||||
|
|
||||||
|
class FeasycomInterface(BTLEUart, BaseInterface):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# BTLEUart(mac=MAC, timeout=5)
|
8
srnemqtt/interfaces/serial.py
Normal file
8
srnemqtt/interfaces/serial.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import serial
|
||||||
|
|
||||||
|
from . import BaseInterface
|
||||||
|
|
||||||
|
|
||||||
|
class SerialInterface(serial.Serial, BaseInterface):
|
||||||
|
pass
|
Loading…
Reference in a new issue