@@ -3,9 +3,10 @@ use crate::{
3
3
serial:: { simple_serial_port:: SimpleSerialPort , SubscriptionSerial } ,
4
4
subscription:: { Predicate , Subscription , SubscriptionService } ,
5
5
unpi:: {
6
- commands:: { get_command_by_name, ParameterValue } ,
7
- LenTypeInfo , MessageType , Subsystem , UnpiPacket ,
6
+ commands:: { get_command_by_name, ParameterValue , ParametersValueMap } ,
7
+ LenTypeInfo , MessageType , SUnpiPacket , Subsystem ,
8
8
} ,
9
+ utils:: warnn,
9
10
} ;
10
11
use futures:: {
11
12
channel:: oneshot:: { self , Receiver , Sender } ,
@@ -16,11 +17,9 @@ use std::{path::PathBuf, sync::Arc};
16
17
//TODO: fix this
17
18
const MAXIMUM_ZIGBEE_PAYLOAD_SIZE : usize = 255 ;
18
19
19
- type Container = Vec < u8 > ;
20
-
21
20
pub struct CC253X < S : SubscriptionSerial > {
22
21
_supports_led : Option < bool > ,
23
- subscriptions : Arc < Mutex < SubscriptionService < UnpiPacket < Container > > > > ,
22
+ subscriptions : Arc < Mutex < SubscriptionService < SUnpiPacket > > > ,
24
23
serial : Arc < Mutex < S > > ,
25
24
}
26
25
@@ -43,25 +42,65 @@ impl CC253X<SimpleSerialPort> {
43
42
}
44
43
}
45
44
45
+ impl < S : SubscriptionSerial > CC253X < S > {
46
+ pub async fn request (
47
+ & self ,
48
+ name : & str ,
49
+ subsystem : Subsystem ,
50
+ parameters : & [ ( & ' static str , ParameterValue ) ] ,
51
+ ) -> Result < ( ) , CoordinatorError > {
52
+ let command =
53
+ get_command_by_name ( & subsystem, name) . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
54
+ let packet = SUnpiPacket :: from_command_owned (
55
+ LenTypeInfo :: OneByte ,
56
+ ( command. command_type , subsystem) ,
57
+ parameters,
58
+ command,
59
+ ) ?;
60
+ self . serial . lock ( ) . await . write ( & packet) . await ?;
61
+ Ok ( ( ) )
62
+ }
63
+
64
+ pub async fn request_with_reply (
65
+ & self ,
66
+ name : & str ,
67
+ subsystem : Subsystem ,
68
+ parameters : & [ ( & ' static str , ParameterValue ) ] ,
69
+ ) -> Result < ParametersValueMap , CoordinatorError > {
70
+ let command =
71
+ get_command_by_name ( & subsystem, name) . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
72
+ let packet = SUnpiPacket :: from_command_owned (
73
+ LenTypeInfo :: OneByte ,
74
+ ( command. command_type , subsystem) ,
75
+ parameters,
76
+ command,
77
+ ) ?;
78
+ let wait = self . wait_for ( "version" , MessageType :: SRESP , Subsystem :: Sys , None ) ;
79
+ let send = async {
80
+ let mut lock = self . serial . lock ( ) . await ;
81
+ lock. write ( & packet) . await
82
+ } ;
83
+ futures:: try_join!( send, wait)
84
+ . map ( |( _, packet) | command. read_and_fill ( packet. payload . as_slice ( ) ) ) ?
85
+ }
86
+ }
87
+
46
88
impl < S : SubscriptionSerial > CC253X < S > {
47
89
pub async fn wait_for (
48
90
& self ,
49
91
name : & str ,
50
92
message_type : MessageType ,
51
93
subsystem : Subsystem ,
52
94
_timeout : Option < std:: time:: Duration > ,
53
- ) -> Result < UnpiPacket < Container > , CoordinatorError > {
95
+ ) -> Result < SUnpiPacket , CoordinatorError > {
54
96
let command =
55
97
get_command_by_name ( & subsystem, name) . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
56
98
let subscriptions = self . subscriptions . clone ( ) ;
57
- let ( tx, rx) : (
58
- Sender < UnpiPacket < Container > > ,
59
- Receiver < UnpiPacket < Container > > ,
60
- ) = oneshot:: channel ( ) ;
99
+ let ( tx, rx) : ( Sender < SUnpiPacket > , Receiver < SUnpiPacket > ) = oneshot:: channel ( ) ;
61
100
{
62
101
let mut s = subscriptions. lock ( ) . await ;
63
102
let subscription = Subscription :: SingleShot (
64
- Predicate ( Box :: new ( move |packet : & UnpiPacket < Container > | {
103
+ Predicate ( Box :: new ( move |packet : & SUnpiPacket | {
65
104
packet. type_subsystem == ( message_type, subsystem)
66
105
&& packet. command == command. id
67
106
} ) ) ,
@@ -70,8 +109,7 @@ impl<S: SubscriptionSerial> CC253X<S> {
70
109
s. subscribe ( subscription) ;
71
110
}
72
111
73
- let packet = rx. await . map_err ( |_| CoordinatorError :: SubscriptionError ) ?;
74
- Ok ( packet)
112
+ rx. await . map_err ( |_| CoordinatorError :: SubscriptionError )
75
113
}
76
114
}
77
115
@@ -90,56 +128,29 @@ impl<S: SubscriptionSerial> Coordinator for CC253X<S> {
90
128
todo ! ( )
91
129
}
92
130
93
- async fn permit_join (
94
- & self ,
95
- _address : u16 ,
96
- _duration : std:: time:: Duration ,
97
- ) -> Result < ( ) , CoordinatorError > {
98
- todo ! ( )
131
+ async fn is_inter_pan_mode ( & self ) -> bool {
132
+ warnn ! ( "is_inter_pan_mode not implemented, assuming false" ) ;
133
+ false
99
134
}
100
135
101
136
async fn version ( & self ) -> Result < Option < ParameterValue > , CoordinatorError > {
102
- let command = get_command_by_name ( & Subsystem :: Sys , "version" )
103
- . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
104
- let serial = self . serial . clone ( ) ;
105
- let wait = self . wait_for ( "version" , MessageType :: SRESP , Subsystem :: Sys , None ) ;
106
- let send = async {
107
- let packet = UnpiPacket :: from_command_owned (
108
- LenTypeInfo :: OneByte ,
109
- ( MessageType :: SREQ , Subsystem :: Sys ) ,
110
- & [ ] ,
111
- command,
112
- ) ?;
113
- serial. lock ( ) . await . write ( & packet) . await ?;
114
- Ok :: < ( ) , CoordinatorError > ( ( ) )
115
- } ;
116
- let ( _s, packet) = futures:: try_join!( send, wait) ?;
117
- let r = command. read_and_fill ( packet. payload . as_slice ( ) ) ?;
118
- Ok ( r. get ( & "majorrel" ) . cloned ( ) )
137
+ let version = self
138
+ . request_with_reply ( "version" , Subsystem :: Sys , & [ ] )
139
+ . await ?;
140
+ Ok ( version. get ( & "majorrel" ) . cloned ( ) )
119
141
}
120
142
121
143
async fn reset ( & self , reset_type : ResetType ) -> Result < ( ) , CoordinatorError > {
122
- let command = get_command_by_name ( & Subsystem :: Sys , "reset_req" )
123
- . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
124
144
let parameters = match reset_type {
125
145
ResetType :: Soft => & [ ( "type" , ParameterValue :: U8 ( 1 ) ) ] ,
126
146
ResetType :: Hard => & [ ( "type" , ParameterValue :: U8 ( 0 ) ) ] ,
127
147
} ;
128
-
129
- let serial = self . serial . clone ( ) ;
130
- let packet = UnpiPacket :: from_command_owned (
131
- LenTypeInfo :: OneByte ,
132
- ( MessageType :: SREQ , Subsystem :: Sys ) ,
133
- parameters,
134
- command,
135
- ) ?;
136
- serial. lock ( ) . await . write ( & packet) . await ?;
148
+ self . request ( "reset_req" , Subsystem :: Sys , parameters)
149
+ . await ?;
137
150
Ok :: < ( ) , CoordinatorError > ( ( ) )
138
151
}
139
152
140
153
async fn set_led ( & self , led_status : LedStatus ) -> Result < ( ) , CoordinatorError > {
141
- let command = get_command_by_name ( & Subsystem :: Util , "led_control" )
142
- . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
143
154
//TODO: const firmwareControlsLed = parseInt(this.version.revision) >= 20211029;
144
155
let firmware_controls_led = true ;
145
156
@@ -167,22 +178,15 @@ impl<S: SubscriptionSerial> Coordinator for CC253X<S> {
167
178
] ,
168
179
} ;
169
180
170
- let serial = self . serial . clone ( ) ;
171
- let packet = UnpiPacket :: from_command_owned (
172
- LenTypeInfo :: OneByte ,
173
- ( MessageType :: SREQ , Subsystem :: Util ) ,
174
- parameters,
175
- command,
176
- ) ?;
177
- serial. lock ( ) . await . write ( & packet) . await ?;
178
- Ok ( ( ) )
181
+ self . request ( "led_control" , Subsystem :: Util , parameters)
182
+ . await
179
183
}
180
184
181
185
async fn change_channel ( & self , channel : u8 ) -> Result < ( ) , CoordinatorError > {
182
186
let parameters = & [
183
- ( "dst_addr " , ParameterValue :: U16 ( 0xffff ) ) ,
187
+ ( "destination_address " , ParameterValue :: U16 ( 0xffff ) ) ,
184
188
(
185
- "dst_addr_mode " ,
189
+ "destination_address_mode " ,
186
190
ParameterValue :: U16 ( AddressMode :: AddrBroadcast as u16 ) ,
187
191
) ,
188
192
(
@@ -196,22 +200,15 @@ impl<S: SubscriptionSerial> Coordinator for CC253X<S> {
196
200
) ,
197
201
( "scan_duration" , ParameterValue :: U8 ( 0xfe ) ) ,
198
202
( "scan_count" , ParameterValue :: U8 ( 0 ) ) ,
199
- ( "nwk_manager_addr " , ParameterValue :: U16 ( 0 ) ) ,
203
+ ( "network_manager_address " , ParameterValue :: U16 ( 0 ) ) ,
200
204
] ;
201
205
202
- let command = get_command_by_name ( & Subsystem :: Zdo , "management_network_update_request" )
203
- . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
204
-
205
- let serial = self . serial . clone ( ) ;
206
- let packet = UnpiPacket :: from_command_owned (
207
- LenTypeInfo :: OneByte ,
208
- ( MessageType :: SREQ , Subsystem :: Zdo ) ,
206
+ self . request (
207
+ "management_network_update_request" ,
208
+ Subsystem :: Zdo ,
209
209
parameters,
210
- command,
211
- ) ?;
212
- serial. lock ( ) . await . write ( & packet) . await ?;
213
-
214
- Ok ( ( ) )
210
+ )
211
+ . await
215
212
}
216
213
217
214
async fn set_transmit_power ( & self , power : i8 ) -> Result < ( ) , CoordinatorError > {
@@ -220,18 +217,7 @@ impl<S: SubscriptionSerial> Coordinator for CC253X<S> {
220
217
( "value" , ParameterValue :: I8 ( power) ) ,
221
218
] ;
222
219
223
- let command = get_command_by_name ( & Subsystem :: Zdo , "stack_tune" )
224
- . ok_or ( CoordinatorError :: NoCommandWithName ) ?;
225
-
226
- let serial = self . serial . clone ( ) ;
227
- let packet = UnpiPacket :: from_command_owned (
228
- LenTypeInfo :: OneByte ,
229
- ( MessageType :: SREQ , Subsystem :: Zdo ) ,
230
- parameters,
231
- command,
232
- ) ?;
233
- serial. lock ( ) . await . write ( & packet) . await ?;
234
- Ok ( ( ) )
220
+ self . request ( "stack_tune" , Subsystem :: Zdo , parameters) . await
235
221
}
236
222
237
223
async fn request_network_address ( _addr : & str ) -> Result < ( ) , CoordinatorError > {
@@ -251,4 +237,36 @@ impl<S: SubscriptionSerial> Coordinator for CC253X<S> {
251
237
) -> Result < Option < Self :: ZclPayload < ' static > > , CoordinatorError > {
252
238
Ok ( None )
253
239
}
240
+
241
+ async fn permit_join (
242
+ & self ,
243
+ seconds : std:: time:: Duration ,
244
+ network_address : Option < u16 > ,
245
+ ) -> Result < ( ) , CoordinatorError > {
246
+ if self . is_inter_pan_mode ( ) . await {
247
+ return Err ( CoordinatorError :: InterpanMode ) ;
248
+ }
249
+ let address_mode =
250
+ network_address. map_or ( AddressMode :: AddrBroadcast , |_| AddressMode :: Addr16bit ) ;
251
+ let destination_address = network_address. unwrap_or ( 0xfffc ) ;
252
+ let parameters = & [
253
+ ( "address_mode" , ParameterValue :: U16 ( address_mode as u16 ) ) ,
254
+ (
255
+ "destination_address" ,
256
+ ParameterValue :: U16 ( destination_address) ,
257
+ ) ,
258
+ (
259
+ "duration" ,
260
+ ParameterValue :: U8 (
261
+ seconds
262
+ . as_secs ( )
263
+ . try_into ( )
264
+ . map_err ( |_| CoordinatorError :: DurationTooLong ) ?,
265
+ ) ,
266
+ ) ,
267
+ ( "tc_significance" , ParameterValue :: U8 ( 0 ) ) ,
268
+ ] ;
269
+ self . request ( "management_permit_join_request" , Subsystem :: Zdo , parameters)
270
+ . await
271
+ }
254
272
}
0 commit comments