use pvxs_sys::{
AlarmSeverity, AlarmStatus, ControlMetadata, DisplayMetadata, NTScalarMetadataBuilder, Server,
};
use std::thread;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Starting EPICS PVA server with managed PVs and metadata...");
pvxs_sys::set_logger_level("pvxs.tcp.io", "CRIT")?;
pvxs_sys::set_logger_level("pvxs.tcp.io", "CRIT").ok();
let server = Server::start_from_env()?;
println!("Server started successfully!");
println!("TCP port: {}", server.tcp_port());
println!("UDP port: {}", server.udp_port());
let metadata = NTScalarMetadataBuilder::new()
.display(DisplayMetadata {
limit_low: -10,
limit_high: 110,
description: "Temperature Sensor".to_string(),
units: "°C".to_string(),
precision: 3,
})
.control(ControlMetadata {
limit_low: -10.0,
limit_high: 110.0,
min_step: 0.1,
})
.alarm_metadata(pvxs_sys::AlarmMetadata {
active: true,
low_alarm_limit: 20.0,
low_warning_limit: 30.0,
high_warning_limit: 90.0,
high_alarm_limit: 105.0,
low_alarm_severity: pvxs_sys::AlarmSeverity::Major,
low_warning_severity: pvxs_sys::AlarmSeverity::Minor,
high_warning_severity: pvxs_sys::AlarmSeverity::Minor,
high_alarm_severity: pvxs_sys::AlarmSeverity::Major,
hysteresis: 1,
});
server.create_pv_double("temperature:sensor1", 25.5, metadata)?;
println!("Created PV: temperature:sensor1 (initial value = 25.5)");
println!("\nTest with:");
println!(" pvget temperature:sensor1");
println!(" pvput temperature:sensor1 75.0");
println!(" pvinfo temperature:sensor1");
println!("\nAlarm ranges:");
println!(" < 20.0: MAJOR/LOLO (low alarm)");
println!(" 20.0 - 30.0: MINOR/LOW (low warning)");
println!(" 30.0 - 90.0: NO_ALARM (normal)");
println!(" 90.0 - 105.0: MINOR/HIGH (high warning)");
println!(" > 105.0: MAJOR/HIHI (high alarm)");
println!("\nPress Ctrl+C to stop...\n");
loop {
thread::sleep(Duration::from_secs(2));
let mut temp = server.fetch_double("temperature:sensor1")?;
if temp.alarm_status >= AlarmStatus::RecordStatus
&& temp.alarm_severity >= AlarmSeverity::Invalid
&& temp.alarm_message.contains("OUT_OF_CONTROL_LIMITS")
{
temp.value -= 1.014; } else {
temp.value += 1.014; }
server.post_double("temperature:sensor1", temp.value)?;
let precision = temp
.display_metadata
.as_ref()
.map_or(2, |d| d.precision as usize);
let units = temp
.display_metadata
.as_ref()
.map_or("", |d| d.units.as_str());
println!(
"Updated temperature to: {:.precision$}{}",
temp.value, units
);
}
}