pytec: measure interval
This commit is contained in:
parent
93ea46d512
commit
b7e6cdbec2
@ -89,7 +89,10 @@ Set report mode to `on` for a continuous stream of input data.
|
|||||||
The scope of this setting is per TCP session.
|
The scope of this setting is per TCP session.
|
||||||
|
|
||||||
|
|
||||||
### Commands
|
### TCP commands
|
||||||
|
|
||||||
|
Send commands as simple text string terminated by `\n`. Responses are
|
||||||
|
formatted as line-delimited JSON.
|
||||||
|
|
||||||
| Syntax | Function |
|
| Syntax | Function |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|
@ -2,7 +2,10 @@ from pytec.client import Client
|
|||||||
|
|
||||||
tec = Client() #(host="localhost", port=6667)
|
tec = Client() #(host="localhost", port=6667)
|
||||||
tec.set_param("s-h", 1, "t0", 20)
|
tec.set_param("s-h", 1, "t0", 20)
|
||||||
|
print(tec.get_pwm())
|
||||||
print(tec.get_pid())
|
print(tec.get_pid())
|
||||||
|
print(tec.get_pwm())
|
||||||
|
print(tec.get_postfilter())
|
||||||
print(tec.get_steinhart_hart())
|
print(tec.get_steinhart_hart())
|
||||||
for data in tec.report_mode():
|
for data in tec.report_mode():
|
||||||
print(data)
|
print(data)
|
||||||
|
@ -39,21 +39,29 @@ series = {
|
|||||||
'i_tec': Series(),
|
'i_tec': Series(),
|
||||||
'tec_i': Series(),
|
'tec_i': Series(),
|
||||||
'tec_u_meas': Series(),
|
'tec_u_meas': Series(),
|
||||||
|
'interval': Series(),
|
||||||
}
|
}
|
||||||
series_lock = Lock()
|
series_lock = Lock()
|
||||||
|
|
||||||
quit = False
|
quit = False
|
||||||
|
last_packet_time = None
|
||||||
|
|
||||||
def recv_data(tec):
|
def recv_data(tec):
|
||||||
|
global last_packet_time
|
||||||
for data in tec.report_mode():
|
for data in tec.report_mode():
|
||||||
if data['channel'] == 0:
|
if data['channel'] == 0:
|
||||||
series_lock.acquire()
|
series_lock.acquire()
|
||||||
try:
|
try:
|
||||||
time = data['time'] / 1000.0
|
time = data['time'] / 1000.0
|
||||||
|
if last_packet_time:
|
||||||
|
data['interval'] = time - last_packet_time
|
||||||
|
last_packet_time = time
|
||||||
|
|
||||||
for k, s in series.items():
|
for k, s in series.items():
|
||||||
v = data[k]
|
if k in data:
|
||||||
if k in data and type(v) is float:
|
v = data[k]
|
||||||
s.append(time, v)
|
if type(v) is float:
|
||||||
|
s.append(time, v)
|
||||||
finally:
|
finally:
|
||||||
series_lock.release()
|
series_lock.release()
|
||||||
|
|
||||||
@ -108,9 +116,11 @@ def animate(i):
|
|||||||
finally:
|
finally:
|
||||||
series_lock.release()
|
series_lock.release()
|
||||||
|
|
||||||
margin_y = 0.01 * (max_y - min_y)
|
if min_x != max_x:
|
||||||
ax.set_xlim(min_x, max_x)
|
ax.set_xlim(min_x, max_x)
|
||||||
ax.set_ylim(min_y - margin_y, max_y + margin_y)
|
if min_y != max_y:
|
||||||
|
margin_y = 0.01 * (max_y - min_y)
|
||||||
|
ax.set_ylim(min_y - margin_y, max_y + margin_y)
|
||||||
|
|
||||||
global legend
|
global legend
|
||||||
legend.remove()
|
legend.remove()
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
import socket
|
import socket
|
||||||
import json
|
import json
|
||||||
|
|
||||||
CHANNELS = 2
|
class CommandError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, host="192.168.1.26", port=23, timeout=None):
|
def __init__(self, host="192.168.1.26", port=23, timeout=None):
|
||||||
self._socket = socket.create_connection((host, port), timeout)
|
self._socket = socket.create_connection((host, port), timeout)
|
||||||
self._lines = [""]
|
self._lines = [""]
|
||||||
|
|
||||||
def _command(self, *command):
|
|
||||||
self._socket.sendall((" ".join(command) + "\n").encode('utf-8'))
|
|
||||||
|
|
||||||
def _read_line(self):
|
def _read_line(self):
|
||||||
# read more lines
|
# read more lines
|
||||||
while len(self._lines) <= 1:
|
while len(self._lines) <= 1:
|
||||||
@ -24,13 +22,19 @@ class Client:
|
|||||||
self._lines = self._lines[1:]
|
self._lines = self._lines[1:]
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
def _command(self, *command):
|
||||||
|
self._socket.sendall((" ".join(command) + "\n").encode('utf-8'))
|
||||||
|
|
||||||
|
line = self._read_line()
|
||||||
|
response = json.loads(line)
|
||||||
|
if "error" in response:
|
||||||
|
raise CommandError(response["error"])
|
||||||
|
return response
|
||||||
|
|
||||||
def _get_conf(self, topic):
|
def _get_conf(self, topic):
|
||||||
self._command(topic)
|
result = [None, None]
|
||||||
result = []
|
for item in self._command(topic):
|
||||||
for channel in range(0, CHANNELS):
|
result[int(item["channel"])] = item
|
||||||
line = self._read_line()
|
|
||||||
conf = json.loads(line)
|
|
||||||
result.append(conf)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_pwm(self):
|
def get_pwm(self):
|
||||||
|
134
src/channels.rs
134
src/channels.rs
@ -1,3 +1,4 @@
|
|||||||
|
use heapless::{consts::{U2, U1024}, Vec};
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
use stm32f4xx_hal::hal;
|
use stm32f4xx_hal::hal;
|
||||||
@ -412,7 +413,7 @@ impl Channels {
|
|||||||
(duty * max, max)
|
(duty * max, max)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report(&mut self, channel: usize) -> Report {
|
fn report(&mut self, channel: usize) -> Report {
|
||||||
let vref = self.channel_state(channel).vref;
|
let vref = self.channel_state(channel).vref;
|
||||||
let (i_set, _) = self.get_i(channel);
|
let (i_set, _) = self.get_i(channel);
|
||||||
let i_tec = self.read_itec(channel);
|
let i_tec = self.read_itec(channel);
|
||||||
@ -441,7 +442,23 @@ impl Channels {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwm_summary(&mut self, channel: usize) -> PwmSummary {
|
pub fn reports_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
||||||
|
let mut reports = Vec::<_, U2>::new();
|
||||||
|
for channel in 0..CHANNELS {
|
||||||
|
let _ = reports.push(self.report(channel));
|
||||||
|
}
|
||||||
|
serde_json_core::to_vec(&reports)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pid_summaries_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
||||||
|
let mut summaries = Vec::<_, U2>::new();
|
||||||
|
for channel in 0..CHANNELS {
|
||||||
|
let _ = summaries.push(self.channel_state(channel).pid.summary(channel));
|
||||||
|
}
|
||||||
|
serde_json_core::to_vec(&summaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pwm_summary(&mut self, channel: usize) -> PwmSummary {
|
||||||
PwmSummary {
|
PwmSummary {
|
||||||
channel,
|
channel,
|
||||||
center: CenterPointJson(self.channel_state(channel).center.clone()),
|
center: CenterPointJson(self.channel_state(channel).center.clone()),
|
||||||
@ -452,19 +469,43 @@ impl Channels {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn postfilter_summary(&mut self, channel: usize) -> PostFilterSummary {
|
pub fn pwm_summaries_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
||||||
|
let mut summaries = Vec::<_, U2>::new();
|
||||||
|
for channel in 0..CHANNELS {
|
||||||
|
let _ = summaries.push(self.pwm_summary(channel));
|
||||||
|
}
|
||||||
|
serde_json_core::to_vec(&summaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn postfilter_summary(&mut self, channel: usize) -> PostFilterSummary {
|
||||||
let rate = self.adc.get_postfilter(channel as u8).unwrap()
|
let rate = self.adc.get_postfilter(channel as u8).unwrap()
|
||||||
.and_then(|filter| filter.output_rate());
|
.and_then(|filter| filter.output_rate());
|
||||||
PostFilterSummary { channel, rate }
|
PostFilterSummary { channel, rate }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn steinhart_hart_summary(&mut self, channel: usize) -> SteinhartHartSummary {
|
pub fn postfilter_summaries_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
||||||
|
let mut summaries = Vec::<_, U2>::new();
|
||||||
|
for channel in 0..CHANNELS {
|
||||||
|
let _ = summaries.push(self.postfilter_summary(channel));
|
||||||
|
}
|
||||||
|
serde_json_core::to_vec(&summaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn steinhart_hart_summary(&mut self, channel: usize) -> SteinhartHartSummary {
|
||||||
let params = self.channel_state(channel).sh.clone();
|
let params = self.channel_state(channel).sh.clone();
|
||||||
SteinhartHartSummary { channel, params }
|
SteinhartHartSummary { channel, params }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn steinhart_hart_summaries_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
||||||
|
let mut summaries = Vec::<_, U2>::new();
|
||||||
|
for channel in 0..CHANNELS {
|
||||||
|
let _ = summaries.push(self.steinhart_hart_summary(channel));
|
||||||
|
}
|
||||||
|
serde_json_core::to_vec(&summaries)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonBuffer = heapless::Vec<u8, heapless::consts::U512>;
|
type JsonBuffer = Vec<u8, U1024>;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Report {
|
pub struct Report {
|
||||||
@ -484,12 +525,6 @@ pub struct Report {
|
|||||||
pid_output: Option<ElectricCurrent>,
|
pid_output: Option<ElectricCurrent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Report {
|
|
||||||
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
|
||||||
serde_json_core::to_vec(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CenterPointJson(CenterPoint);
|
pub struct CenterPointJson(CenterPoint);
|
||||||
|
|
||||||
// used in JSON encoding, not for config
|
// used in JSON encoding, not for config
|
||||||
@ -529,91 +564,14 @@ pub struct PwmSummary {
|
|||||||
max_i_neg: PwmSummaryField<ElectricCurrent>,
|
max_i_neg: PwmSummaryField<ElectricCurrent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PwmSummary {
|
|
||||||
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
|
||||||
serde_json_core::to_vec(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct PostFilterSummary {
|
pub struct PostFilterSummary {
|
||||||
channel: usize,
|
channel: usize,
|
||||||
rate: Option<f32>,
|
rate: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PostFilterSummary {
|
|
||||||
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
|
||||||
serde_json_core::to_vec(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct SteinhartHartSummary {
|
pub struct SteinhartHartSummary {
|
||||||
channel: usize,
|
channel: usize,
|
||||||
params: steinhart_hart::Parameters,
|
params: steinhart_hart::Parameters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SteinhartHartSummary {
|
|
||||||
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
|
||||||
serde_json_core::to_vec(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn report_to_json() {
|
|
||||||
// `/ 1.1` results in values with a really long serialization
|
|
||||||
let report = Report {
|
|
||||||
channel: 0,
|
|
||||||
time: 3200,
|
|
||||||
adc: Some(ElectricPotential::new::<volt>(0.65 / 1.1)),
|
|
||||||
sens: Some(ElectricalResistance::new::<ohm>(10000.0 / 1.1)),
|
|
||||||
temperature: Some(30.0 / 1.1),
|
|
||||||
pid_engaged: false,
|
|
||||||
i_set: ElectricCurrent::new::<ampere>(0.5 / 1.1),
|
|
||||||
vref: ElectricPotential::new::<volt>(1.5 / 1.1),
|
|
||||||
dac_value: ElectricPotential::new::<volt>(2.0 / 1.1),
|
|
||||||
dac_feedback: ElectricPotential::new::<volt>(2.0 / 1.1),
|
|
||||||
i_tec: ElectricPotential::new::<volt>(2.0 / 1.1),
|
|
||||||
tec_i: ElectricCurrent::new::<ampere>(0.2 / 1.1),
|
|
||||||
tec_u_meas: ElectricPotential::new::<volt>(2.0 / 1.1),
|
|
||||||
pid_output: Some(ElectricCurrent::new::<ampere>(0.5 / 1.1)),
|
|
||||||
};
|
|
||||||
let buf = report.to_json().unwrap();
|
|
||||||
assert_eq!(buf[0], b'{');
|
|
||||||
assert_eq!(buf[buf.len() - 1], b'}');
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn pwm_summary_to_json() {
|
|
||||||
let value = 1.0 / 1.1;
|
|
||||||
let max = 5.0 / 1.1;
|
|
||||||
|
|
||||||
let pwm_summary = PwmSummary {
|
|
||||||
channel: 0,
|
|
||||||
center: CenterPointJson(CenterPoint::Vref),
|
|
||||||
i_set: PwmSummaryField {
|
|
||||||
value: ElectricCurrent::new::<ampere>(value),
|
|
||||||
max: ElectricCurrent::new::<ampere>(max),
|
|
||||||
},
|
|
||||||
max_v: PwmSummaryField {
|
|
||||||
value: ElectricPotential::new::<volt>(value),
|
|
||||||
max: ElectricPotential::new::<volt>(max),
|
|
||||||
},
|
|
||||||
max_i_pos: PwmSummaryField {
|
|
||||||
value: ElectricCurrent::new::<ampere>(value),
|
|
||||||
max: ElectricCurrent::new::<ampere>(max),
|
|
||||||
},
|
|
||||||
max_i_neg: PwmSummaryField {
|
|
||||||
value: ElectricCurrent::new::<ampere>(value),
|
|
||||||
max: ElectricCurrent::new::<ampere>(max),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let buf = pwm_summary.to_json().unwrap();
|
|
||||||
assert_eq!(buf[0], b'{');
|
|
||||||
assert_eq!(buf[buf.len() - 1], b'}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
144
src/main.rs
144
src/main.rs
@ -81,7 +81,8 @@ const TCP_PORT: u16 = 23;
|
|||||||
fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool {
|
fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool {
|
||||||
let send_free = socket.send_capacity() - socket.send_queue();
|
let send_free = socket.send_capacity() - socket.send_queue();
|
||||||
if data.len() > send_free + 1 {
|
if data.len() > send_free + 1 {
|
||||||
// Not enough buffer space, skip report for now
|
// Not enough buffer space, skip report for now,
|
||||||
|
// instead of sending incomplete line
|
||||||
warn!(
|
warn!(
|
||||||
"TCP socket has only {}/{} needed {}",
|
"TCP socket has only {}/{} needed {}",
|
||||||
send_free + 1, socket.send_capacity(), data.len(),
|
send_free + 1, socket.send_capacity(), data.len(),
|
||||||
@ -103,17 +104,6 @@ fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_to(channel: usize, channels: &mut Channels, socket: &mut TcpSocket) -> bool {
|
|
||||||
match channels.report(channel).to_json() {
|
|
||||||
Ok(buf) =>
|
|
||||||
send_line(socket, &buf[..]),
|
|
||||||
Err(e) => {
|
|
||||||
error!("unable to serialize report: {:?}", e);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialization and main loop
|
/// Initialization and main loop
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[entry]
|
#[entry]
|
||||||
@ -221,68 +211,79 @@ fn main() -> ! {
|
|||||||
socket.close()
|
socket.close()
|
||||||
} else if socket.can_send() && socket.can_recv() {
|
} else if socket.can_send() && socket.can_recv() {
|
||||||
match socket.recv(|buf| session.feed(buf)) {
|
match socket.recv(|buf| session.feed(buf)) {
|
||||||
Ok(SessionInput::Nothing) => {}
|
Ok(SessionInput::Nothing) => {
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
|
}
|
||||||
Ok(SessionInput::Command(command)) => match command {
|
Ok(SessionInput::Command(command)) => match command {
|
||||||
Command::Quit =>
|
Command::Quit =>
|
||||||
socket.close(),
|
socket.close(),
|
||||||
Command::Reporting(_reporting) => {
|
Command::Reporting(_reporting) => {
|
||||||
// handled by session
|
// handled by session
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::Reporting) => {
|
Command::Show(ShowCommand::Reporting) => {
|
||||||
let _ = writeln!(socket, "{{ \"report\": {:?} }}", session.reporting());
|
let _ = writeln!(socket, "{{ \"report\": {:?} }}", session.reporting());
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::Input) => {
|
Command::Show(ShowCommand::Input) => {
|
||||||
for channel in 0..CHANNELS {
|
match channels.reports_json() {
|
||||||
report_to(channel, &mut channels, &mut socket);
|
Ok(buf) => {
|
||||||
|
send_line(&mut socket, &buf[..]);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("unable to serialize report: {:?}", e);
|
||||||
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::Pid) => {
|
Command::Show(ShowCommand::Pid) => {
|
||||||
for channel in 0..CHANNELS {
|
match channels.pid_summaries_json() {
|
||||||
match channels.channel_state(channel).pid.summary(channel).to_json() {
|
Ok(buf) => {
|
||||||
Ok(buf) => {
|
send_line(&mut socket, &buf);
|
||||||
send_line(&mut socket, &buf);
|
}
|
||||||
}
|
Err(e) => {
|
||||||
Err(e) =>
|
error!("unable to serialize pid summary: {:?}", e);
|
||||||
error!("unable to serialize pid summary: {:?}", e),
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::Pwm) => {
|
Command::Show(ShowCommand::Pwm) => {
|
||||||
for channel in 0..CHANNELS {
|
match channels.pwm_summaries_json() {
|
||||||
match channels.pwm_summary(channel).to_json() {
|
Ok(buf) => {
|
||||||
Ok(buf) => {
|
send_line(&mut socket, &buf);
|
||||||
send_line(&mut socket, &buf);
|
}
|
||||||
}
|
Err(e) => {
|
||||||
Err(e) =>
|
error!("unable to serialize pwm summary: {:?}", e);
|
||||||
error!("unable to serialize pwm summary: {:?}", e),
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::SteinhartHart) => {
|
Command::Show(ShowCommand::SteinhartHart) => {
|
||||||
for channel in 0..CHANNELS {
|
match channels.steinhart_hart_summaries_json() {
|
||||||
match channels.steinhart_hart_summary(channel).to_json() {
|
Ok(buf) => {
|
||||||
Ok(buf) => {
|
send_line(&mut socket, &buf);
|
||||||
send_line(&mut socket, &buf);
|
}
|
||||||
}
|
Err(e) => {
|
||||||
Err(e) =>
|
error!("unable to serialize steinhart-hart summaries: {:?}", e);
|
||||||
error!("unable to serialize steinhart-hart summary: {:?}", e),
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::PostFilter) => {
|
Command::Show(ShowCommand::PostFilter) => {
|
||||||
for channel in 0..CHANNELS {
|
match channels.postfilter_summaries_json() {
|
||||||
match channels.postfilter_summary(channel).to_json() {
|
Ok(buf) => {
|
||||||
Ok(buf) => {
|
send_line(&mut socket, &buf);
|
||||||
send_line(&mut socket, &buf);
|
}
|
||||||
}
|
Err(e) => {
|
||||||
Err(e) =>
|
error!("unable to serialize postfilter summary: {:?}", e);
|
||||||
error!("unable to serialize postfilter summary: {:?}", e),
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::PwmPid { channel } => {
|
Command::PwmPid { channel } => {
|
||||||
channels.channel_state(channel).pid_engaged = true;
|
channels.channel_state(channel).pid_engaged = true;
|
||||||
leds.g3.on();
|
leds.g3.on();
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::Pwm { channel, pin, value } => {
|
Command::Pwm { channel, pin, value } => {
|
||||||
match pin {
|
match pin {
|
||||||
@ -306,6 +307,7 @@ fn main() -> ! {
|
|||||||
channels.set_max_i_neg(channel, current);
|
channels.set_max_i_neg(channel, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::CenterPoint { channel, center } => {
|
Command::CenterPoint { channel, center } => {
|
||||||
let (i_tec, _) = channels.get_i(channel);
|
let (i_tec, _) = channels.get_i(channel);
|
||||||
@ -314,6 +316,7 @@ fn main() -> ! {
|
|||||||
if !state.pid_engaged {
|
if !state.pid_engaged {
|
||||||
channels.set_i(channel, i_tec);
|
channels.set_i(channel, i_tec);
|
||||||
}
|
}
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::Pid { channel, parameter, value } => {
|
Command::Pid { channel, parameter, value } => {
|
||||||
let pid = &mut channels.channel_state(channel).pid;
|
let pid = &mut channels.channel_state(channel).pid;
|
||||||
@ -336,6 +339,7 @@ fn main() -> ! {
|
|||||||
IntegralMax =>
|
IntegralMax =>
|
||||||
pid.parameters.integral_max = value as f32,
|
pid.parameters.integral_max = value as f32,
|
||||||
}
|
}
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::SteinhartHart { channel, parameter, value } => {
|
Command::SteinhartHart { channel, parameter, value } => {
|
||||||
let sh = &mut channels.channel_state(channel).sh;
|
let sh = &mut channels.channel_state(channel).sh;
|
||||||
@ -345,29 +349,41 @@ fn main() -> ! {
|
|||||||
B => sh.b = value,
|
B => sh.b = value,
|
||||||
R0 => sh.r0 = ElectricalResistance::new::<ohm>(value),
|
R0 => sh.r0 = ElectricalResistance::new::<ohm>(value),
|
||||||
}
|
}
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::PostFilter { channel, rate: None } => {
|
Command::PostFilter { channel, rate: None } => {
|
||||||
channels.adc.set_postfilter(channel as u8, None).unwrap();
|
channels.adc.set_postfilter(channel as u8, None).unwrap();
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::PostFilter { channel, rate: Some(rate) } => {
|
Command::PostFilter { channel, rate: Some(rate) } => {
|
||||||
let filter = ad7172::PostFilter::closest(rate);
|
let filter = ad7172::PostFilter::closest(rate);
|
||||||
match filter {
|
match filter {
|
||||||
Some(filter) =>
|
Some(filter) => {
|
||||||
channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap(),
|
channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap();
|
||||||
None =>
|
send_line(&mut socket, b"{}");
|
||||||
error!("unable to choose postfilter for rate {:.3}", rate),
|
}
|
||||||
|
None => {
|
||||||
|
error!("unable to choose postfilter for rate {:.3}", rate);
|
||||||
|
send_line(&mut socket, b"{{\"error\": \"unable to choose postfilter rate\"}}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Load { channel } => {
|
Command::Load { channel } => {
|
||||||
for c in 0..CHANNELS {
|
for c in 0..CHANNELS {
|
||||||
if channel.is_none() || channel == Some(c) {
|
if channel.is_none() || channel == Some(c) {
|
||||||
match store.read_value::<ChannelConfig>(CHANNEL_CONFIG_KEY[c]) {
|
match store.read_value::<ChannelConfig>(CHANNEL_CONFIG_KEY[c]) {
|
||||||
Ok(Some(config)) =>
|
Ok(Some(config)) => {
|
||||||
config.apply(&mut channels, c),
|
config.apply(&mut channels, c);
|
||||||
Ok(None) =>
|
send_line(&mut socket, b"{}");
|
||||||
error!("flash config not found"),
|
}
|
||||||
Err(e) =>
|
Ok(None) => {
|
||||||
error!("unable to load config from flash: {:?}", e),
|
error!("flash config not found");
|
||||||
|
send_line(&mut socket, b"{{\"error\": \"flash config not found\"}}");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("unable to load config from flash: {:?}", e);
|
||||||
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,9 +392,13 @@ fn main() -> ! {
|
|||||||
for c in 0..CHANNELS {
|
for c in 0..CHANNELS {
|
||||||
if channel.is_none() || channel == Some(c) {
|
if channel.is_none() || channel == Some(c) {
|
||||||
let config = ChannelConfig::new(&mut channels, c);
|
let config = ChannelConfig::new(&mut channels, c);
|
||||||
let _ = store
|
match store.write_value(CHANNEL_CONFIG_KEY[c], &config, &mut store_value_buf) {
|
||||||
.write_value(CHANNEL_CONFIG_KEY[c], &config, &mut store_value_buf)
|
Ok(()) => {}
|
||||||
.map_err(|e| error!("unable to save channel {} config to flash: {:?}", c, e));
|
Err(e) => {
|
||||||
|
error!("unable to save channel {} config to flash: {:?}", c, e);
|
||||||
|
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,6 +407,7 @@ fn main() -> ! {
|
|||||||
.write_value("ipv4", &config, [0; 16])
|
.write_value("ipv4", &config, [0; 16])
|
||||||
.map_err(|e| error!("unable to save ipv4 config to flash: {:?}", e));
|
.map_err(|e| error!("unable to save ipv4 config to flash: {:?}", e));
|
||||||
new_ipv4_config = Some(config);
|
new_ipv4_config = Some(config);
|
||||||
|
send_line(&mut socket, b"{}");
|
||||||
}
|
}
|
||||||
Command::Reset => {
|
Command::Reset => {
|
||||||
for i in 0..CHANNELS {
|
for i in 0..CHANNELS {
|
||||||
@ -405,8 +426,15 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
} else if socket.can_send() {
|
} else if socket.can_send() {
|
||||||
if let Some(channel) = session.is_report_pending() {
|
if let Some(channel) = session.is_report_pending() {
|
||||||
if report_to(channel, &mut channels, &mut socket) {
|
match channels.reports_json() {
|
||||||
session.mark_report_sent(channel);
|
Ok(buf) => {
|
||||||
|
send_line(&mut socket, &buf[..]);
|
||||||
|
session.mark_report_sent(channel);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("unable to serialize report: {:?}", e);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,6 @@ impl Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonBuffer = heapless::Vec<u8, heapless::consts::U360>;
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct Summary {
|
pub struct Summary {
|
||||||
channel: usize,
|
channel: usize,
|
||||||
@ -101,12 +99,6 @@ pub struct Summary {
|
|||||||
integral: f64,
|
integral: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Summary {
|
|
||||||
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
|
||||||
serde_json_core::to_vec(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user