2022-06-14 16:45:43 -07:00
//
// T e l e m e t r y C o n f i g . s w i f t
// M e s h t a s t i c A p p l e
//
// C o p y r i g h t ( c ) G a r t h V a n d e r H o u w e n 6 / 1 3 / 2 2 .
//
import SwiftUI
2022-06-22 09:05:56 -07:00
enum SensorTypes : Int , CaseIterable , Identifiable {
// / N o e x t e r n a l t e l e m e t r y s e n s o r e x p l i c i t l y s e t
case notSet = 0
// / M o d e r a t e a c c u r a c y t e m p e r a t u r e
case dht11 = 1
// / H i g h a c c u r a c y t e m p e r a t u r e
case ds18B20 = 2
// / M o d e r a t e a c c u r a c y t e m p e r a t u r e a n d h u m i d i t y
case dht12 = 3
// / M o d e r a t e a c c u r a c y t e m p e r a t u r e a n d h u m i d i t y
case dht21 = 4
// / M o d e r a t e a c c u r a c y t e m p e r a t u r e a n d h u m i d i t y
case dht22 = 5
// / H i g h a c c u r a c y t e m p e r a t u r e , p r e s s u r e , h u m i d i t y
case bme280 = 6
// / H i g h a c c u r a c y t e m p e r a t u r e , p r e s s u r e , h u m i d i t y , a n d a i r r e s i s t a n c e
case bme680 = 7
// / V e r y h i g h a c c u r a c y t e m p e r a t u r e
case mcp9808 = 8
// / M o d e r a t e a c c u r a c y t e m p e r a t u r e a n d h u m i d i t y
case shtc3 = 9
// / M o d e r a t e a c c u r a c y c u r r e n t a n d v o l t a g e
case ina260 = 10
// / M o d e r a t e a c c u r a c y c u r r e n t a n d v o l t a g e
case ina219 = 11
var id : Int { self . rawValue }
var description : String {
get {
switch self {
case . notSet :
return " Not Set "
case . dht11 :
2022-06-22 15:52:51 -07:00
return " DHT11 - Temperature "
2022-06-22 09:05:56 -07:00
case . ds18B20 :
2022-06-22 15:52:51 -07:00
return " DS18B20 - Temperature "
2022-06-22 09:05:56 -07:00
case . dht12 :
2022-06-22 15:52:51 -07:00
return " DHT12 - Temperature & humidity "
2022-06-22 09:05:56 -07:00
case . dht21 :
2022-06-22 15:52:51 -07:00
return " DHT21 - Temperature & humidity "
2022-06-22 09:05:56 -07:00
case . dht22 :
2022-06-22 15:52:51 -07:00
return " DHT22 - Temperature & humidity "
2022-06-22 09:05:56 -07:00
case . bme280 :
2022-06-22 15:52:51 -07:00
return " BME280 - Temp, pressure & humidity "
2022-06-22 09:05:56 -07:00
case . bme680 :
2022-06-22 15:52:51 -07:00
return " BME680 - Temp, pressure, humidity & air resistance "
2022-06-22 09:05:56 -07:00
case . mcp9808 :
2022-06-22 15:52:51 -07:00
return " MCP9808 - Temperature "
2022-06-22 09:05:56 -07:00
case . shtc3 :
2022-06-22 15:52:51 -07:00
return " SHTC3 - Temperature & humidity "
2022-06-22 09:05:56 -07:00
case . ina260 :
2022-06-22 15:52:51 -07:00
return " INA260 - Current & voltage "
2022-06-22 09:05:56 -07:00
case . ina219 :
2022-06-22 15:52:51 -07:00
return " INA219 - Current & voltage "
2022-06-22 09:05:56 -07:00
}
}
}
}
// D e f a u l t o f 0 i s o f f
enum ErrorRecoveryIntervals : Int , CaseIterable , Identifiable {
case off = 0
case fifteenSeconds = 15
case thirtySeconds = 30
case oneMinute = 60
case fiveMinutes = 300
case tenMinutes = 600
case fifteenMinutes = 900
case thirtyMinutes = 1800
case oneHour = 3600
var id : Int { self . rawValue }
var description : String {
get {
switch self {
case . off :
2022-06-22 15:52:51 -07:00
return " Unset "
2022-06-22 09:05:56 -07:00
case . fifteenSeconds :
return " Fifteen Seconds "
case . thirtySeconds :
return " Thirty Seconds "
case . oneMinute :
return " One Minute "
case . fiveMinutes :
return " Five Minutes "
case . tenMinutes :
return " Ten Minutes "
case . fifteenMinutes :
return " Fifteen Minutes "
case . thirtyMinutes :
return " Thirty Minutes "
case . oneHour :
return " One Hour "
}
}
}
}
enum UpdateIntervals : Int , CaseIterable , Identifiable {
case fifteenSeconds = 15
case thirtySeconds = 30
case oneMinute = 60
case fiveMinutes = 300
case tenMinutes = 600
2022-06-22 15:52:51 -07:00
case fifteenMinutes = 0
2022-06-22 09:05:56 -07:00
case thirtyMinutes = 1800
case oneHour = 3600
2022-06-22 15:52:51 -07:00
case twoHours = 7200
case threeHours = 10800
case fourHours = 14400
case fiveHours = 18000
case sixHours = 21600
case twelveHours = 43200
case eighteenHours = 64800
case twentyFourHours = 86400
2022-06-22 09:05:56 -07:00
var id : Int { self . rawValue }
var description : String {
get {
switch self {
case . fifteenSeconds :
return " Fifteen Seconds "
case . thirtySeconds :
return " Thirty Seconds "
case . oneMinute :
return " One Minute "
case . fiveMinutes :
return " Five Minutes "
case . tenMinutes :
return " Ten Minutes "
case . fifteenMinutes :
return " Fifteen Minutes "
case . thirtyMinutes :
return " Thirty Minutes "
case . oneHour :
return " One Hour "
2022-06-22 15:52:51 -07:00
case . twoHours :
return " Two Hours "
case . threeHours :
return " Three Hours "
case . fourHours :
return " Four Hours "
case . fiveHours :
return " Five Hours "
case . sixHours :
return " Six Hours "
case . twelveHours :
return " Twelve Hours "
case . eighteenHours :
return " Eighteen Hours "
case . twentyFourHours :
return " Twenty Four Hours "
2022-06-22 09:05:56 -07:00
}
}
}
}
2022-06-14 16:45:43 -07:00
struct TelemetryConfig : View {
@ Environment ( \ . managedObjectContext ) var context
@ EnvironmentObject var bleManager : BLEManager
2022-06-22 09:05:56 -07:00
@ State var deviceUpdateInterval = 0
@ State var environmentUpdateInterval = 0
@ State var environmentMeasurementEnabled = false
@ State var environmentSensorType = 0
@ State var environmentScreenEnabled = false
@ State var environmentDisplayFahrenheit = false
@ State var environmentSensorPin = 0
@ State var environmentRecoveryInterval = 0
@ State var environmentReadErrorCountThreshold = 0
2022-06-14 16:45:43 -07:00
var body : some View {
VStack {
Form {
2022-06-22 09:05:56 -07:00
Section ( header : Text ( " Update Intervals " ) ) {
Picker ( " Device Metrics " , selection : $ deviceUpdateInterval ) {
ForEach ( UpdateIntervals . allCases ) { ui in
Text ( ui . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
2022-06-22 15:52:51 -07:00
Text ( " How often device metrics are sent out over the mesh. Default is 15 minutes. " )
. font ( . caption )
2022-06-22 09:05:56 -07:00
Picker ( " Sensor Metrics " , selection : $ environmentUpdateInterval ) {
ForEach ( UpdateIntervals . allCases ) { ui in
Text ( ui . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
2022-06-22 15:52:51 -07:00
Text ( " How often sensor metrics are sent out over the mesh. Default is 15 minutes. " )
. font ( . caption )
2022-06-22 09:05:56 -07:00
}
Section ( header : Text ( " Sensor Options " ) ) {
Toggle ( isOn : $ environmentMeasurementEnabled ) {
Label ( " Enabled " , systemImage : " chart.xyaxis.line " )
}
2022-06-22 15:52:51 -07:00
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2022-06-22 09:05:56 -07:00
Picker ( " Sensor " , selection : $ environmentSensorType ) {
ForEach ( SensorTypes . allCases ) { st in
Text ( st . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Toggle ( isOn : $ environmentScreenEnabled ) {
Label ( " Show on device screen " , systemImage : " display " )
}
2022-06-22 15:52:51 -07:00
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2022-06-22 09:05:56 -07:00
Toggle ( isOn : $ environmentDisplayFahrenheit ) {
Label ( " Display Fahrenheit " , systemImage : " thermometer " )
}
2022-06-22 15:52:51 -07:00
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2022-06-22 09:05:56 -07:00
Picker ( " GPIO Pin for sensor readings " , selection : $ environmentSensorPin ) {
2022-06-22 15:52:51 -07:00
ForEach ( 0. . < 40 ) {
2022-06-22 09:05:56 -07:00
if $0 = = 0 {
2022-06-22 15:52:51 -07:00
Text ( " Unset " )
2022-06-22 09:05:56 -07:00
} else {
2022-06-22 15:52:51 -07:00
Text ( " Pin \( $0 ) " )
2022-06-22 09:05:56 -07:00
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
}
Section ( header : Text ( " Errors " ) ) {
Picker ( " Error Count Threshold " , selection : $ environmentReadErrorCountThreshold ) {
ForEach ( 0. . < 101 ) {
if $0 = = 0 {
2022-06-22 15:52:51 -07:00
Text ( " Unset " )
2022-06-22 09:05:56 -07:00
} else if $0 % 5 = = 0 {
Text ( " \( $0 ) " )
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " Sometimes sensor reads can fail. If this happens, we will retry a configurable number of attempts, each attempt will be delayed by the minimum required refresh rate for that sensor " )
. font ( . caption )
Picker ( " Error Recovery Interval " , selection : $ environmentRecoveryInterval ) {
ForEach ( ErrorRecoveryIntervals . allCases ) { eri in
Text ( eri . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " Sometimes we can end up with more failures than our error count threshold. In this case, we will stop trying to read from the sensor for a while. Wait this long until trying to read from the sensor again " )
. font ( . caption )
}
2022-06-14 16:45:43 -07:00
}
. navigationTitle ( " Telemetry Config " )
. navigationBarItems ( trailing :
ZStack {
2022-06-17 18:20:30 -07:00
ConnectedDevice ( bluetoothOn : bleManager . isSwitchedOn , deviceConnected : bleManager . connectedPeripheral != nil , name : ( bleManager . connectedPeripheral != nil ) ? bleManager . connectedPeripheral . shortName : " ????? " )
2022-06-14 16:45:43 -07:00
} )
. onAppear {
self . bleManager . context = context
}
. navigationViewStyle ( StackNavigationViewStyle ( ) )
}
}
}