Skip to content

Commit

Permalink
Rename to iotic
Browse files Browse the repository at this point in the history
  • Loading branch information
mincequi committed Oct 27, 2023
1 parent 45301e3 commit 8321d05
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 163 deletions.
13 changes: 7 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.14)

project(elsewhere
VERSION 0.1.0
project(iotic
VERSION 0.2.0
LANGUAGES C CXX)

include(FetchContent)
Expand Down Expand Up @@ -36,13 +36,13 @@ if(BUILD_TESTS)
add_subdirectory(tests)
endif()

add_executable(elsewhere
add_executable(iotic
src/main.cpp
src/AppBackend.cpp
src/Statistics.cpp
)

target_link_libraries(elsewhere
target_link_libraries(iotic
Threads::Threads
${CMAKE_DL_LIBS}
common
Expand All @@ -55,8 +55,9 @@ target_link_libraries(elsewhere
webserver
)

install(TARGETS elsewhere DESTINATION bin)
install(FILES ${PROJECT_SOURCE_DIR}/etc/elsewhere.conf DESTINATION /etc)
install(TARGETS iotic DESTINATION bin)
install(FILES ${PROJECT_SOURCE_DIR}/etc/iotic.conf DESTINATION /var/lib/iotic)
install(FILES ${PROJECT_SOURCE_DIR}/debian/iotic.service DESTINATION /usr/lib/systemd/system)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Manuel Weichselbaumer <mincequi@web.de>") #required
Expand Down
126 changes: 57 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,60 @@
# Iotic

<img width="288" src="https://github.com/mincequi/ElsewhereEdge/assets/1805183/c5087dca-a473-4a1c-911a-faaf7f295660"> <img width="288" src="https://github.com/mincequi/ElsewhereEdge/assets/1805183/b4371fbd-d778-4dce-8918-90e0c6b39376">

Iotic is a multi-purpose IoT device manager which focuses on thermal and electrical energy.
Photovoltaic systems, electric vehicles and heatings can be brought together for smart energy management.
It also can act as a data collector and export to InfluxDB and MQTT. This allows multiple scenarios (e.g.):
- SunSpec - MQTT gateway
- PV surplus controlled charging of electric cars
- PV surplus water controlled water heating
- Peak shaving

Its main features are:
- Modbus support
- SunSpec device support (Solar inverters, smart meters)
- Shelly support (1 and 1PM)
- go-e Charger support
- MQTT export
- InfluxDB export
- Web app

## Requirements
# iotic

<img height="480" src="https://github.com/mincequi/iotic/assets/1805183/cba31985-6c84-4bd5-ac69-3322199a25e0"> <img height="480" src="https://github.com/mincequi/iotic/assets/1805183/72d89e72-f6ea-4acf-84db-8b53d311a39a">

Iotic is a multi-purpose IoT device manager which focuses on electric and thermal energy management.
Its main feature is pv surplus charging of your electric vehicle.

# Features
## Device support
### Solar inverters
Currently, the following SunSpec models are supported: 101, 103, 160, 203. So, **ANY** solar inverter and smart meter that supports SunSpec / Modbus should also be supported here. As of now, the following devices are successfully tested:
- SMA STP8.0-3AV-40 / STP10.0-3AV-40
- SMA STP 15000TL-30 / 20000TL-30 /25000TL-30
- SMA SB 3000TL-21 / 3600TL-21 / 4000TL-21 / 5000TL-21

### Smart meters
- elgris SMART METER WiFi

### EV stations
- go-e Charger

### Smart plugs/relays
- Shelly 1 / 1PM

## Auto detection
All supporterd things are automatically discovered using different technologies:

### Modbus SunSpec devices
Iotic will scan your subnet with a mask of /24. E.g. if an instance is running on a host with IPv4 address 192.168.12.34, all IP addresses from 192.168.12.1 - 192.168.12.254 will be port scanned on port 502. If a valid SunSpec header is returned, the host will be considered as a valid SunSpec device.
This incoporates a small limitation, that currently there is only **one** Modbus device per host address supported, even though Modbus TCP would support multiple SunSpec devices per IP address.

### HTTP devices
Devices with an HTTP API are discovered using mDNS service discovery (like go-eCharger and Shelly).

## PV surplus electric vehicle charging
iotic implements several strategies to realize PC surplus charging of electric vehicles. It will auto-adapt the charging power to PV excess.

# Requirements
- C++17
- Qt >= 6.4 Core Network SerialBus WebSockets HttpServer (currently not working with Qt5)
- Qt >= 6.4 Core Network SerialBus WebSockets HttpServer (not working with Qt5)
- Flutter

## Installation (from source)
### Raspberry Pi OS
In order to compile and run iotic on Raspberry Pi OS, we need some updated packages.
Please check the following steps (and potentially adapt commands to your needs).
# Installation (Debian/Ubuntu)
## Raspberry Pi OS
You need at least Bookworm (not working with Bullseye).
Installation
```
wget http://ftp.debian.org/debian/pool/main/d/debian-archive-keyring/debian-archive-keyring_2023.4_all.deb
sudo dpkg -i debian-archive-keyring_2023.4_all.deb
sudo sh -c 'echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list'
sudo apt install ./iotic_0.2.0_armhf.deb
```
Starting
```
sudo systemctl start iotic.service # start-up service.
sudo systemctl enable iotic.service # start-up service on each reboot.
```

### Prerequisites (Debian/Ubuntu)
# Compiling (Debian/Ubuntu)
## Prerequisites
```
sudo apt install \
build-essential \
Expand All @@ -53,57 +73,25 @@ flutter # init flutter first
```

```
git clone https://github.com/mincequi/ElsewhereEdge
cd ElsewhereEdge/src/webapp
flutter build web --web-renderer html --no-tree-shake-icons
git clone https://github.com/mincequi/iotic
cd iotic/src/webapp
flutter build web --web-renderer html
cd ../..
mkdir build
cd build
cmake ..
make
```

## Auto detection
Currently, there are some auto discoveries implemented.

### SunSpec
Iotic will scan your subnet with a mask of /24. E.g. if an instance is running on a host with IPv4 address 192.168.12.34, all IP addresses from 192.168.12.1 - 192.168.12.254 will be port scanned on port 502. If a valid SunSpec header is returned, the host will be considered as a valid SunSpec device.
This incoporates a small limitation, that currently there is only **one** Modbus device per host address supported, even though Modbus TCP would support multiple SunSpec devices per IP address.

### go-e Charger
go-e Chargers are discovered using mDNS service discovery.

### Shelly
Shellies are discovered using mDNS service discovery.

## MQTT API
# MQTT API
After being connected, the discovered things will be polled and published via MQTT every 5 seconds.

The MQTT topic follows this scheme: `/elsewhere_<mac address>/<unique sunspec id>/<model id>/`.
The MQTT topic follows this scheme: `/iotic_<mac address>/<unique sunspec id>/<model id>/`.
Under this topic there are two sub-topics: `live` and `stats`. The *statistics* show the min/max values of the current day, as well as some other collected information. Thus, the *stats* topic will not be updated as often as the *live* topic, which gets an update every 3 seconds.

The payload is formatted as JSON.

## Device support
Currently, the following SunSpec models are supported: 101, 103, 160, 203. So, **ANY** solar inverter and smart meter that supports SunSpec / Modbus should also be supported here. As of now, the following devices are successfully tested:
### Solar inverters
- SMA STP8.0-3AV-40 / STP10.0-3AV-40
- SMA STP 15000TL-30 / 20000TL-30 /25000TL-30
- SMA SB 3000TL-21 / 3600TL-21 / 4000TL-21 / 5000TL-21

### Smart meters
- elgris SMART METER WiFi

### EV stations
- go-e Charger

### Smart plugs/relays
- Shelly 1 / 1PM

## Planned features
- config file
- debian package
# Planned features
- command line interface
- read battery inverters
- control wallboxes
- InfluxDB
12 changes: 12 additions & 0 deletions debian/iotic.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=Iotic service
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/iotic
User=iotic
Group=iotic

[Install]
WantedBy=multi-user.target
12 changes: 7 additions & 5 deletions debian/postinst
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#!/bin/sh

#https://stackoverflow.com/questions/71066592/how-to-correctly-add-a-systemd-service-to-a-cpack-generated-debian-package

set -e

case "$1" in
configure)
# create elsewhere user if not there already
if ! getent passwd elsewhere >/dev/null; then
adduser --disabled-password --quiet --system --home /var/lib/elsewhere --group elsewhere
# create iotic user if not there already
if ! getent passwd iotic >/dev/null; then
adduser --disabled-password --quiet --system --home /var/lib/iotic --group iotic
fi
chown elsewhere:elsewhere /var/lib/elsewhere
rm -rf /var/lib/elsewhere/* > /dev/null 2>&1 || true
chown -R iotic:iotic /var/lib/iotic
#rm -rf /var/lib/iotic/* > /dev/null 2>&1 || true
;;

abort-upgrade|abort-remove|abort-deconfigure)
Expand Down
8 changes: 4 additions & 4 deletions debian/postrm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/sh

if [ "$1" = "purge" ]; then
deluser --quiet --system elsewhere > /dev/null || true
delgroup --quiet --system elsewhere > /dev/null || true
# Cleanup /var/lib/elsewhere
rm -rf /var/lib/elsewhere > /dev/null 2>&1 || true
deluser --quiet --system iotic > /dev/null || true
delgroup --quiet --system iotic > /dev/null || true
# Cleanup /var/lib/iotic
rm -rf /var/lib/iotic > /dev/null 2>&1 || true
fi
38 changes: 0 additions & 38 deletions etc/elsewhere.conf

This file was deleted.

3 changes: 3 additions & 0 deletions etc/iotic.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[general]
discovery_interval = 60000
thing_interval = 2000
2 changes: 1 addition & 1 deletion src/AppBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ AppBackend::AppBackend()

#ifdef USE_INFLUXDB
// Setup InfluxExporter
const QString db = "elsewhere_" + util::getMacAddress().remove(':');
const QString db = "iotic_" + util::getMacAddress().remove(':');
_influxExporter = InfluxExporter::build(db.toStdString())
.host("localhost")
.port(8086);
Expand Down
25 changes: 17 additions & 8 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(FETCHCONTENT_QUIET FALSE)
set(CMAKE_CXX_FLAGS "-DLOGURU_WITH_STREAMS -DLOGURU_USE_FMTLIB" CACHE INTERNAL "")
set(CMAKE_CXX_FLAGS "-DLOGURU_WITH_STREAMS" CACHE INTERNAL "")

#set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON CACHE INTERNAL "Auto moc")
Expand All @@ -15,22 +15,31 @@ FetchContent_Declare(loguru
)
FetchContent_MakeAvailable(loguru)

FetchContent_Declare(fmt
URL https://github.com/fmtlib/fmt/archive/refs/tags/10.1.1.tar.gz
)
FetchContent_MakeAvailable(fmt)
#FetchContent_Declare(fmt
# URL https://github.com/fmtlib/fmt/archive/refs/tags/10.1.1.tar.gz
#)
#if(NOT fmt_POPULATED)
# FetchContent_Populate(fmt)
# add_subdirectory(${fmt_SOURCE_DIR} ${fmt_BINARY_DIR} EXCLUDE_FROM_ALL)
#endif()

FetchContent_Declare(magic_enum
GIT_REPOSITORY https://github.com/Neargye/magic_enum.git
GIT_TAG v0.7.3
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(magic_enum)
if(NOT magic_enum_POPULATED)
FetchContent_Populate(magic_enum)
add_subdirectory(${magic_enum_SOURCE_DIR} ${magic_enum_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()

FetchContent_Declare(rpp
URL https://github.com/victimsnino/ReactivePlusPlus/archive/refs/tags/v0.2.3.tar.gz
)
FetchContent_MakeAvailable(rpp)
if(NOT rpp_POPULATED)
FetchContent_Populate(rpp)
add_subdirectory(${rpp_SOURCE_DIR} ${rpp_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()

add_library(common STATIC
Logger.cpp
Expand All @@ -52,7 +61,7 @@ PUBLIC
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::SerialBus
fmt::fmt
#fmt::fmt
magic_enum
rpp
rppqt
Expand Down
11 changes: 7 additions & 4 deletions src/common/OffsetTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <limits>
#include <vector>

static const int defaultOffset = 4;

static const std::vector<int> offsetTable = { // 6th root of ten
std::numeric_limits<int16_t>::min(),
-500,
Expand All @@ -20,14 +22,15 @@ static const std::vector<int> offsetTable = { // 6th root of ten
500,
700,
1000,
1500, // this prevents from switching off
2000, // this prevents from switching off - with some extra headroom
3000, // this prevents phase switching to 3
5000, // this prevents phase switching to 1
1500, // this prevents from switching off (acutally not)
2000, // this prevents from switching down to off - with some extra headroom
3000, // this prevents phase switching up to 3
5000, // this prevents phase switching down to 1
7000,
10000,
// 15000
// 20000
//std::numeric_limits<int16_t>::max(),
};

static const std::vector<int> alt2OffsetTable = { // 10th root of ten
Expand Down
Loading

0 comments on commit 8321d05

Please sign in to comment.