Skip to content

Commit 430a735

Browse files
committed
feat: tiny improvements
- do not reuse modbus context - enable RS485 mode before sending commands - allow 2 installations of hackdose on 1 device
1 parent 89308cc commit 430a735

6 files changed

Lines changed: 60 additions & 20 deletions

File tree

server/hackdose2.service

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[Unit]
2+
Description=Hackdose2
3+
4+
[Service]
5+
ExecStart=/usr/bin/hackdose-server2 --config /etc/hackdose2.yaml
6+
Restart=on-failure
7+
EnvironmentFile=/etc/environment
8+
9+
[Install]
10+
WantedBy=multi-user.target

server/install2.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
set -eux
3+
4+
pushd ../app
5+
trunk build --release
6+
popd
7+
8+
source profiles/$PROFILE_NAME/.env
9+
cargo build --target=$TARGET --release
10+
sshpass -p $PI_PASSWORD scp -C -P$PI_SSH_PORT hackdose2.service $PI_USER@$PI_HOST:/etc/systemd/system
11+
sshpass -p $PI_PASSWORD ssh -p $PI_SSH_PORT $PI_USER@$PI_HOST 'systemctl enable hackdose2.service'
12+
sshpass -p $PI_PASSWORD ssh -p $PI_SSH_PORT $PI_USER@$PI_HOST 'systemctl stop hackdose2.service'
13+
sshpass -p $PI_PASSWORD scp -C -P$PI_SSH_PORT ../target/$TARGET/release/hackdose-server $PI_USER@$PI_HOST:/usr/bin/hackdose-server2
14+
sshpass -p $PI_PASSWORD scp -C -P$PI_SSH_PORT profiles/$PROFILE_NAME/hackdose.yaml $PI_USER@$PI_HOST:/etc/hackdose2.yaml
15+
sshpass -p $PI_PASSWORD ssh -p $PI_SSH_PORT $PI_USER@$PI_HOST 'systemctl start hackdose2.service'

server/src/actors/marstek.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ mod marstek_registers {
1010
pub(super) const STATE: u16 = 0xa41a;
1111
pub(super) const FORCIBLE_CHARGE_WATTS: u16 = 0xa424;
1212
pub(super) const FORCIBLE_DISCHARGE_WATTS: u16 = 0xa425;
13+
pub(super) const RS485_CONTROL_MODE: u16 = 0xA410;
1314

1415
pub(super) const STATE_CHARGE: u16 = 1;
1516
pub(super) const STATE_DISCHARGE: u16 = 2;
17+
pub(super) const RS485_ENABLED: u16 = 0x55aa;
1618
}
1719

1820
#[derive(Serialize, Deserialize, Clone)]
@@ -48,6 +50,12 @@ impl Regulator for MarstekCharge {
4850

4951
task::spawn(async move {
5052
let mut ctx = slave.connect().await.unwrap();
53+
let _ = ctx
54+
.write_single_register(
55+
marstek_registers::RS485_CONTROL_MODE,
56+
marstek_registers::RS485_ENABLED,
57+
)
58+
.await;
5159
let _ = ctx
5260
.write_single_register(marstek_registers::STATE, marstek_registers::STATE_CHARGE)
5361
.await;

server/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub(crate) struct Configuration {
3636
power_measurement: PowerMeasurement,
3737
lower_limit: isize,
3838
upper_limit: isize,
39+
port: Option<usize>,
3940
}
4041

4142
#[derive(Serialize, Deserialize, Clone)]

server/src/rest/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use axum::{
77
routing::get,
88
Json, Router,
99
};
10+
use chrono::format::format;
1011
use hackdose_server_shared::{DataPoint, Range};
1112
use hackdose_sml_parser::application::{domain::AnyValue, obis::Obis};
1213
use mime_guess::mime;
@@ -80,7 +81,10 @@ pub(crate) async fn serve_rest_endpoint(
8081
energy_data: EnergyData,
8182
config: &Configuration,
8283
) {
83-
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
84+
let listener =
85+
tokio::net::TcpListener::bind(format!("0.0.0.0:{}", config.port.unwrap_or(8080)))
86+
.await
87+
.unwrap();
8488
let app_state = AppState {
8589
energy_data: energy_data,
8690
smart_meter_state: SmartMeterState(mutex),

server/src/smart_meter/generic_modbus.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,31 @@ pub(crate) fn spawn_modbus_producer(
2222

2323
tokio::spawn(async move {
2424
loop {
25-
let mut ctx = con.modbus_slave.connect().await.unwrap();
2625
loop {
27-
let v = timeout(
28-
Duration::from_secs(5),
29-
ctx.read_holding_registers(con.register, 1),
30-
)
31-
.await;
32-
if let Ok(Ok(Ok(v))) = v {
33-
match v.first() {
34-
Some(v) => {
35-
let date = Utc::now();
36-
let v = (*v as i16) as i32;
37-
let data = DataPoint { date, value: v };
38-
energy_data.put(data).await;
39-
energy_data.log_data(data).await;
40-
let _ = cloned_tx.send((v, date)).await;
26+
let ctx = con.modbus_slave.connect().await;
27+
if let Ok(mut ctx) = ctx {
28+
let v = timeout(
29+
Duration::from_secs(5),
30+
ctx.read_holding_registers(con.register, 1),
31+
)
32+
.await;
33+
if let Ok(Ok(Ok(v))) = v {
34+
match v.first() {
35+
Some(v) => {
36+
let date = Utc::now();
37+
let v = (*v as i16) as i32;
38+
let data = DataPoint { date, value: v };
39+
energy_data.put(data).await;
40+
energy_data.log_data(data).await;
41+
let _ = cloned_tx.send((v, date)).await;
42+
}
43+
None => (),
4144
}
42-
None => (),
45+
} else {
46+
break;
4347
}
44-
} else {
45-
break;
48+
sleep(Duration::from_millis(con.poll_intervall_millis as u64)).await;
4649
}
47-
sleep(Duration::from_millis(con.poll_intervall_millis as u64)).await;
4850
}
4951
}
5052
});

0 commit comments

Comments
 (0)