meshcore-cli 1.2.14__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcore-cli
3
- Version: 1.2.14
3
+ Version: 1.3.0
4
4
  Summary: Command line interface to meshcore companion radios
5
5
  Project-URL: Homepage, https://github.com/fdlamotte/meshcore-cli
6
6
  Project-URL: Issues, https://github.com/fdlamotte/meshcore-cli/issues
@@ -58,22 +58,25 @@ Init files can also be defined for a given device, meshcore-cli will look for `&
58
58
 
59
59
  ### Arguments
60
60
 
61
- Arguments mostly deals with ble connection
61
+ Arguments mostly deals with connection to the node
62
62
 
63
63
  <pre>
64
64
  -h : prints this help
65
65
  -v : prints version
66
66
  -j : json output (disables init file)
67
67
  -D : debug
68
- -S : performs a ble scan and ask for device
69
- -l : list available ble devices and exit
70
- -T &lt;timeout> : timeout for the ble scan (-S and -l) default 2s
71
- -a &lt;address> : specifies device address (can be a name)
72
- -d &lt;name> : filter meshcore devices with name or address
73
- -t &lt;hostname> : connects via tcp/ip
74
- -p &lt;port> : specifies tcp port (default 5000)
75
- -s &lt;port> : use serial port &lt;port>
76
- -b &lt;baudrate> : specify baudrate
68
+ -S : scan for devices and show a selector
69
+ -l : list available ble/serial devices and exit
70
+ -T &lt;timeout&gt; : timeout for the ble scan (-S and -l) default 2s
71
+ -a &lt;address&gt; : specifies device address (can be a name)
72
+ -d &lt;name&gt; : filter meshcore devices with name or address
73
+ -P : forces pairing via the OS
74
+ -t &lt;hostname&gt; : connects via tcp/ip
75
+ -p &lt;port&gt; : specifies tcp port (default 5000)
76
+ -s &lt;port&gt; : use serial port &lt;port&gt;
77
+ -b &lt;baudrate&gt; : specify baudrate
78
+ -C : toggles classic mode for prompt
79
+ -c &lt;on/off&gt; : disables most of color output if off
77
80
  </pre>
78
81
 
79
82
  ### Available Commands
@@ -81,60 +84,70 @@ Arguments mostly deals with ble connection
81
84
  Commands are given after arguments, they can be chained and some have shortcuts. Also prefixing a command with a dot `.` will force it to output json instead of synthetic result.
82
85
 
83
86
  <pre>
87
+ ?&lt;cmd&gt; may give you some more help about cmd
84
88
  General commands
85
89
  chat : enter the chat (interactive) mode
86
- chat_to &lt;ct> : enter chat with contact to
87
- script &lt;filename> : execute commands in filename
90
+ chat_to &lt;ct&gt; : enter chat with contact to
91
+ script &lt;filename&gt; : execute commands in filename
88
92
  infos : print informations about the node i
89
93
  self_telemetry : print own telemtry t
90
94
  card : export this node URI e
91
95
  ver : firmware version v
92
96
  reboot : reboots node
93
- sleep &lt;secs> : sleeps for a given amount of secs s
94
- wait_key : wait until user presses &lt;Enter> wk
95
- Messenging
96
- msg &lt;name> &lt;msg> : send message to node by name m {
97
+ sleep &lt;secs&gt; : sleeps for a given amount of secs s
98
+ wait_key : wait until user presses &lt;Enter&gt; wk
99
+ apply_to &lt;f&gt; &lt;cmds&gt; : sends cmds to contacts matching f at
100
+ Messaging
101
+ msg &lt;name&gt; &lt;msg&gt; : send message to node by name m {
97
102
  wait_ack : wait an ack wa }
98
- chan &lt;nb> &lt;msg> : send message to channel number &lt;nb> ch
99
- public &lt;msg> : send message to public channel (0) dch
103
+ chan &lt;nb&gt; &lt;msg&gt; : send message to channel number &lt;nb&gt; ch
104
+ public &lt;msg&gt; : send message to public channel (0) dch
100
105
  recv : reads next msg r
101
106
  wait_msg : wait for a message and read it wm
102
107
  sync_msgs : gets all unread msgs from the node sm
103
108
  msgs_subscribe : display msgs as they arrive ms
104
- get_channel &lt;n> : get info for channel n
109
+ get_channels : prints all channel info
110
+ get_channel &lt;n&gt; : get info for channel (by number or name)
105
111
  set_channel n nm k : set channel info (nb, name, key)
112
+ remove_channel &lt;n&gt; : remove channel (by number or name)
113
+ scope &lt;s&gt; : sets node's flood scope
106
114
  Management
107
115
  advert : sends advert a
108
116
  floodadv : flood advert
109
- get &lt;param> : gets a param, "get help" for more
110
- set &lt;param> &lt;value> : sets a param, "set help" for more
111
- time &lt;epoch> : sets time to given epoch
117
+ get &lt;param&gt; : gets a param, \"get help\" for more
118
+ set &lt;param&gt; &lt;value&gt; : sets a param, \"set help\" for more
119
+ time &lt;epoch&gt; : sets time to given epoch
112
120
  clock : get current time
113
121
  clock sync : sync device clock st
122
+ node_discover &lt;filter&gt; : discovers nodes based on their type nd
114
123
  Contacts
115
124
  contacts / list : gets contact list lc
116
- contact_info &lt;ct> : prints information for contact ct ci
117
- contact_timeout &lt;ct> v : sets temp default timeout for contact
118
- share_contact &lt;ct> : share a contact with others sc
119
- export_contact &lt;ct> : get a contact's URI ec
120
- import_contact &lt;URI> : import a contact from its URI ic
121
- remove_contact &lt;ct> : removes a contact from this node
122
- path &lt;ct> : diplays path for a contact
123
- reset_path &lt;ct> : resets path to a contact to flood rp
124
- change_path &lt;ct> &lt;pth> : change the path to a contact cp
125
- change_flags &lt;ct> &lt;f> : change contact flags (tel_l|tel_a|star)cf
126
- req_telemetry &lt;ct> : prints telemetry data as json rt
127
- req_mma &lt;ct> : requests min/max/avg for a sensor rm
128
- req_acl &lt;ct> : requests access control list for sensor
125
+ reload_contacts : force reloading all contacts rc
126
+ contact_info &lt;ct&gt; : prints information for contact ct ci
127
+ contact_timeout &lt;ct&gt; v : sets temp default timeout for contact
128
+ share_contact &lt;ct&gt; : share a contact with others sc
129
+ export_contact &lt;ct&gt; : get a contact's URI ec
130
+ import_contact &lt;URI&gt; : import a contact from its URI ic
131
+ remove_contact &lt;ct&gt; : removes a contact from this node
132
+ path &lt;ct&gt; : diplays path for a contact
133
+ disc_path &lt;ct&gt; : discover new path and display dp
134
+ reset_path &lt;ct&gt; : resets path to a contact to flood rp
135
+ change_path &lt;ct&gt; &lt;pth&gt; : change the path to a contact cp
136
+ change_flags &lt;ct&gt; &lt;f&gt; : change contact flags (tel_l|tel_a|star)cf
137
+ req_telemetry &lt;ct&gt; : prints telemetry data as json rt
138
+ req_mma &lt;ct&gt; : requests min/max/avg for a sensor rm
139
+ req_acl &lt;ct&gt; : requests access control list for sensor
129
140
  pending_contacts : show pending contacts
130
- add_pending &lt;key> : manually add pending contact from key
131
- flush_pending : flush pending contact clist
141
+ add_pending &lt;pending&gt; : manually add pending contact
142
+ flush_pending : flush pending contact list
132
143
  Repeaters
133
- login &lt;name> &lt;pwd> : log into a node (rep) with given pwd l
134
- logout &lt;name> : log out of a repeater
135
- cmd &lt;name> &lt;cmd> : sends a command to a repeater (no ack) c [
144
+ login &lt;name&gt; &lt;pwd&gt; : log into a node (rep) with given pwd l
145
+ logout &lt;name&gt; : log out of a repeater
146
+ cmd &lt;name&gt; &lt;cmd&gt; : sends a command to a repeater (no ack) c [
136
147
  wmt8 : wait for a msg (reply) with a timeout ]
137
- req_status &lt;name> : requests status from a node rs
148
+ req_status &lt;name&gt; : requests status from a node rs
149
+ req_neighbours &lt;name&gt; : requests for neighbours in binary form rn
150
+ trace &lt;path&gt; : run a trace, path is comma separated
138
151
  </pre>
139
152
 
140
153
  ### Interactive Mode
@@ -147,14 +160,70 @@ You'll get a prompt with the name of your node. From here you can type meshcore-
147
160
 
148
161
  The `to` command is specific to chat mode, it lets you enter the recipient for next command. By default you're on your node but you can enter other nodes or public rooms. Here are some examples :
149
162
 
150
- - `to <nodename>` : will enter nodename
163
+ - `to <dest>` : will enter dest (node or channel)
151
164
  - `to /`, `to ~` : will go to the root (your node)
152
165
  - `to ..` : will go to the last node (it will switch between the two last nodes, this is just a 1-depth history)
153
166
  - `to !` : will switch to the node you received last message from
154
167
 
155
- When you are connected to a node, the behaviour will depend on the node type, if you're on a chat node, it will send messages by default and you can chat. On a repeater or a room server, it will send commands (autocompletioin has been set to comply with the CommonCli class of meshcore). To send a message through a room you'll have to prefix the message with a quote or use the send command.
168
+ When you are in a node, the behaviour will depend on the node type, if you're on a chat node, it will send messages by default and you can chat. On a repeater or a room server, it will send commands (autocompletion has been set to comply with the CommonCli class of meshcore). To send a message through a room you'll have to prefix the message with a quote or use the send command.
156
169
 
157
- You can alse set a channel as recipient, `to public` will switch to the public channel, and `to ch1` to channel 1.
170
+ The `/` character is used to bypass the node you have currently selected using `to`:
171
+ - `/<cmd>` issues cmd command on the root
172
+ - `/<node>/<cmd>` will send cmd to selected node
173
+ - `/<dest> <msg>` will send msg to dest (channel or node)
174
+
175
+ #### Flood Scope in interactive mode
176
+
177
+ Flood scope has recently been introduced in meshcore (from `v1.10.0`). It limits the scope of packets to regions, using transport codes in the frame.
178
+
179
+ When entering chat mode, scope will be reset to `*`, meaning classic flood.
180
+
181
+ You can switch scope using the `scope` command, or postfixing the `to` command with `%<scope>`.
182
+
183
+ Scope can also be applied to a command using `%` before the scope name. For instance `login%#Morbihan` will limit diffusion of the login command (which is usually sent flood to get the path to a repeater) to the `#Morbihan` region.
184
+
185
+ #### Channel echoes
186
+
187
+ It's sometimes interesting to know the path taken by a message received from a channel or which repeaters have repeated a sent message.
188
+
189
+ The app give you the information by listening `rx_log` from the device, when obtained the information is attached to the message and can be read.
190
+
191
+ In meshcore-cli I went lower-level by implementing channel echoes. When activated (with `/set channel_echoes on`), all the channel messages will be printed on the terminal along with the SNR and path taken. When sending a message, you'll have all the repeats from 0-hop repeaters as echoes, and when a message is received, you should see information about the received message, but also all the instances of the same message that might have reached you from another path.
192
+
193
+ In the example below, a msg has been sent between two repeaters, 21 and 25. 25 repeated the message and 21 the repeat and both echoes came back to the node with different SNRs.
194
+
195
+ ```
196
+ f1down/#fdl|*> 8
197
+ #fdl f1down: 8 [25] -4.75-112
198
+ #fdl f1down: 8 [2521] 1.00-109
199
+ ```
200
+
201
+ ### Issuing batch commands to contacts with apply to
202
+
203
+ `apply_to <f> <cmd>` : applies cmd to contacts matching filter `<f>` it can be used to apply the same command to a pool of repeaters, or remove some contacts matching a condition.
204
+
205
+ Filter is constructed with comma separated fields :
206
+
207
+ - `u`, matches modification time `<` or `>` than a timestamp (can also be days hours or minutes ago if followed by `d`,`h` or `m`)
208
+ - `t`, matches the type (1: client, 2: repeater, 3: room, 4: sensor)
209
+ - `h`, matches number of hops
210
+ - `d`, direct, similar to `h>-1`
211
+ - `f`, flood, similar to `h<0` or `h=-1`
212
+
213
+ Commands should be written as if in interactive mode, if writing from the commandline don't forget to use commas to clearly delimit fields.
214
+
215
+ Note: Some commands like `contact_name` (aka `cn`), `reset_path` (aka `rp`), `forget_password` (aka `fp`) can be chained. There is also a `sleep` command taking an optional time parameter. The sleep will be issued after the command, it helps limiting rate through repeaters ...
216
+
217
+ #### Examples
218
+
219
+ ```
220
+ # removes all clients that have not been updated in last 2 days
221
+ at u<2d,t=1 remove_contact
222
+ # gives traces to repeaters that have been updated in the last 24h and are direct
223
+ at t=2,u>1d,d cn trace
224
+ # tries to do flood login to all repeaters
225
+ at t=2 rp login
226
+ ```
158
227
 
159
228
  ## Examples
160
229
 
@@ -40,22 +40,25 @@ Init files can also be defined for a given device, meshcore-cli will look for `&
40
40
 
41
41
  ### Arguments
42
42
 
43
- Arguments mostly deals with ble connection
43
+ Arguments mostly deals with connection to the node
44
44
 
45
45
  <pre>
46
46
  -h : prints this help
47
47
  -v : prints version
48
48
  -j : json output (disables init file)
49
49
  -D : debug
50
- -S : performs a ble scan and ask for device
51
- -l : list available ble devices and exit
52
- -T &lt;timeout> : timeout for the ble scan (-S and -l) default 2s
53
- -a &lt;address> : specifies device address (can be a name)
54
- -d &lt;name> : filter meshcore devices with name or address
55
- -t &lt;hostname> : connects via tcp/ip
56
- -p &lt;port> : specifies tcp port (default 5000)
57
- -s &lt;port> : use serial port &lt;port>
58
- -b &lt;baudrate> : specify baudrate
50
+ -S : scan for devices and show a selector
51
+ -l : list available ble/serial devices and exit
52
+ -T &lt;timeout&gt; : timeout for the ble scan (-S and -l) default 2s
53
+ -a &lt;address&gt; : specifies device address (can be a name)
54
+ -d &lt;name&gt; : filter meshcore devices with name or address
55
+ -P : forces pairing via the OS
56
+ -t &lt;hostname&gt; : connects via tcp/ip
57
+ -p &lt;port&gt; : specifies tcp port (default 5000)
58
+ -s &lt;port&gt; : use serial port &lt;port&gt;
59
+ -b &lt;baudrate&gt; : specify baudrate
60
+ -C : toggles classic mode for prompt
61
+ -c &lt;on/off&gt; : disables most of color output if off
59
62
  </pre>
60
63
 
61
64
  ### Available Commands
@@ -63,60 +66,70 @@ Arguments mostly deals with ble connection
63
66
  Commands are given after arguments, they can be chained and some have shortcuts. Also prefixing a command with a dot `.` will force it to output json instead of synthetic result.
64
67
 
65
68
  <pre>
69
+ ?&lt;cmd&gt; may give you some more help about cmd
66
70
  General commands
67
71
  chat : enter the chat (interactive) mode
68
- chat_to &lt;ct> : enter chat with contact to
69
- script &lt;filename> : execute commands in filename
72
+ chat_to &lt;ct&gt; : enter chat with contact to
73
+ script &lt;filename&gt; : execute commands in filename
70
74
  infos : print informations about the node i
71
75
  self_telemetry : print own telemtry t
72
76
  card : export this node URI e
73
77
  ver : firmware version v
74
78
  reboot : reboots node
75
- sleep &lt;secs> : sleeps for a given amount of secs s
76
- wait_key : wait until user presses &lt;Enter> wk
77
- Messenging
78
- msg &lt;name> &lt;msg> : send message to node by name m {
79
+ sleep &lt;secs&gt; : sleeps for a given amount of secs s
80
+ wait_key : wait until user presses &lt;Enter&gt; wk
81
+ apply_to &lt;f&gt; &lt;cmds&gt; : sends cmds to contacts matching f at
82
+ Messaging
83
+ msg &lt;name&gt; &lt;msg&gt; : send message to node by name m {
79
84
  wait_ack : wait an ack wa }
80
- chan &lt;nb> &lt;msg> : send message to channel number &lt;nb> ch
81
- public &lt;msg> : send message to public channel (0) dch
85
+ chan &lt;nb&gt; &lt;msg&gt; : send message to channel number &lt;nb&gt; ch
86
+ public &lt;msg&gt; : send message to public channel (0) dch
82
87
  recv : reads next msg r
83
88
  wait_msg : wait for a message and read it wm
84
89
  sync_msgs : gets all unread msgs from the node sm
85
90
  msgs_subscribe : display msgs as they arrive ms
86
- get_channel &lt;n> : get info for channel n
91
+ get_channels : prints all channel info
92
+ get_channel &lt;n&gt; : get info for channel (by number or name)
87
93
  set_channel n nm k : set channel info (nb, name, key)
94
+ remove_channel &lt;n&gt; : remove channel (by number or name)
95
+ scope &lt;s&gt; : sets node's flood scope
88
96
  Management
89
97
  advert : sends advert a
90
98
  floodadv : flood advert
91
- get &lt;param> : gets a param, "get help" for more
92
- set &lt;param> &lt;value> : sets a param, "set help" for more
93
- time &lt;epoch> : sets time to given epoch
99
+ get &lt;param&gt; : gets a param, \"get help\" for more
100
+ set &lt;param&gt; &lt;value&gt; : sets a param, \"set help\" for more
101
+ time &lt;epoch&gt; : sets time to given epoch
94
102
  clock : get current time
95
103
  clock sync : sync device clock st
104
+ node_discover &lt;filter&gt; : discovers nodes based on their type nd
96
105
  Contacts
97
106
  contacts / list : gets contact list lc
98
- contact_info &lt;ct> : prints information for contact ct ci
99
- contact_timeout &lt;ct> v : sets temp default timeout for contact
100
- share_contact &lt;ct> : share a contact with others sc
101
- export_contact &lt;ct> : get a contact's URI ec
102
- import_contact &lt;URI> : import a contact from its URI ic
103
- remove_contact &lt;ct> : removes a contact from this node
104
- path &lt;ct> : diplays path for a contact
105
- reset_path &lt;ct> : resets path to a contact to flood rp
106
- change_path &lt;ct> &lt;pth> : change the path to a contact cp
107
- change_flags &lt;ct> &lt;f> : change contact flags (tel_l|tel_a|star)cf
108
- req_telemetry &lt;ct> : prints telemetry data as json rt
109
- req_mma &lt;ct> : requests min/max/avg for a sensor rm
110
- req_acl &lt;ct> : requests access control list for sensor
107
+ reload_contacts : force reloading all contacts rc
108
+ contact_info &lt;ct&gt; : prints information for contact ct ci
109
+ contact_timeout &lt;ct&gt; v : sets temp default timeout for contact
110
+ share_contact &lt;ct&gt; : share a contact with others sc
111
+ export_contact &lt;ct&gt; : get a contact's URI ec
112
+ import_contact &lt;URI&gt; : import a contact from its URI ic
113
+ remove_contact &lt;ct&gt; : removes a contact from this node
114
+ path &lt;ct&gt; : diplays path for a contact
115
+ disc_path &lt;ct&gt; : discover new path and display dp
116
+ reset_path &lt;ct&gt; : resets path to a contact to flood rp
117
+ change_path &lt;ct&gt; &lt;pth&gt; : change the path to a contact cp
118
+ change_flags &lt;ct&gt; &lt;f&gt; : change contact flags (tel_l|tel_a|star)cf
119
+ req_telemetry &lt;ct&gt; : prints telemetry data as json rt
120
+ req_mma &lt;ct&gt; : requests min/max/avg for a sensor rm
121
+ req_acl &lt;ct&gt; : requests access control list for sensor
111
122
  pending_contacts : show pending contacts
112
- add_pending &lt;key> : manually add pending contact from key
113
- flush_pending : flush pending contact clist
123
+ add_pending &lt;pending&gt; : manually add pending contact
124
+ flush_pending : flush pending contact list
114
125
  Repeaters
115
- login &lt;name> &lt;pwd> : log into a node (rep) with given pwd l
116
- logout &lt;name> : log out of a repeater
117
- cmd &lt;name> &lt;cmd> : sends a command to a repeater (no ack) c [
126
+ login &lt;name&gt; &lt;pwd&gt; : log into a node (rep) with given pwd l
127
+ logout &lt;name&gt; : log out of a repeater
128
+ cmd &lt;name&gt; &lt;cmd&gt; : sends a command to a repeater (no ack) c [
118
129
  wmt8 : wait for a msg (reply) with a timeout ]
119
- req_status &lt;name> : requests status from a node rs
130
+ req_status &lt;name&gt; : requests status from a node rs
131
+ req_neighbours &lt;name&gt; : requests for neighbours in binary form rn
132
+ trace &lt;path&gt; : run a trace, path is comma separated
120
133
  </pre>
121
134
 
122
135
  ### Interactive Mode
@@ -129,14 +142,70 @@ You'll get a prompt with the name of your node. From here you can type meshcore-
129
142
 
130
143
  The `to` command is specific to chat mode, it lets you enter the recipient for next command. By default you're on your node but you can enter other nodes or public rooms. Here are some examples :
131
144
 
132
- - `to <nodename>` : will enter nodename
145
+ - `to <dest>` : will enter dest (node or channel)
133
146
  - `to /`, `to ~` : will go to the root (your node)
134
147
  - `to ..` : will go to the last node (it will switch between the two last nodes, this is just a 1-depth history)
135
148
  - `to !` : will switch to the node you received last message from
136
149
 
137
- When you are connected to a node, the behaviour will depend on the node type, if you're on a chat node, it will send messages by default and you can chat. On a repeater or a room server, it will send commands (autocompletioin has been set to comply with the CommonCli class of meshcore). To send a message through a room you'll have to prefix the message with a quote or use the send command.
150
+ When you are in a node, the behaviour will depend on the node type, if you're on a chat node, it will send messages by default and you can chat. On a repeater or a room server, it will send commands (autocompletion has been set to comply with the CommonCli class of meshcore). To send a message through a room you'll have to prefix the message with a quote or use the send command.
138
151
 
139
- You can alse set a channel as recipient, `to public` will switch to the public channel, and `to ch1` to channel 1.
152
+ The `/` character is used to bypass the node you have currently selected using `to`:
153
+ - `/<cmd>` issues cmd command on the root
154
+ - `/<node>/<cmd>` will send cmd to selected node
155
+ - `/<dest> <msg>` will send msg to dest (channel or node)
156
+
157
+ #### Flood Scope in interactive mode
158
+
159
+ Flood scope has recently been introduced in meshcore (from `v1.10.0`). It limits the scope of packets to regions, using transport codes in the frame.
160
+
161
+ When entering chat mode, scope will be reset to `*`, meaning classic flood.
162
+
163
+ You can switch scope using the `scope` command, or postfixing the `to` command with `%<scope>`.
164
+
165
+ Scope can also be applied to a command using `%` before the scope name. For instance `login%#Morbihan` will limit diffusion of the login command (which is usually sent flood to get the path to a repeater) to the `#Morbihan` region.
166
+
167
+ #### Channel echoes
168
+
169
+ It's sometimes interesting to know the path taken by a message received from a channel or which repeaters have repeated a sent message.
170
+
171
+ The app give you the information by listening `rx_log` from the device, when obtained the information is attached to the message and can be read.
172
+
173
+ In meshcore-cli I went lower-level by implementing channel echoes. When activated (with `/set channel_echoes on`), all the channel messages will be printed on the terminal along with the SNR and path taken. When sending a message, you'll have all the repeats from 0-hop repeaters as echoes, and when a message is received, you should see information about the received message, but also all the instances of the same message that might have reached you from another path.
174
+
175
+ In the example below, a msg has been sent between two repeaters, 21 and 25. 25 repeated the message and 21 the repeat and both echoes came back to the node with different SNRs.
176
+
177
+ ```
178
+ f1down/#fdl|*> 8
179
+ #fdl f1down: 8 [25] -4.75-112
180
+ #fdl f1down: 8 [2521] 1.00-109
181
+ ```
182
+
183
+ ### Issuing batch commands to contacts with apply to
184
+
185
+ `apply_to <f> <cmd>` : applies cmd to contacts matching filter `<f>` it can be used to apply the same command to a pool of repeaters, or remove some contacts matching a condition.
186
+
187
+ Filter is constructed with comma separated fields :
188
+
189
+ - `u`, matches modification time `<` or `>` than a timestamp (can also be days hours or minutes ago if followed by `d`,`h` or `m`)
190
+ - `t`, matches the type (1: client, 2: repeater, 3: room, 4: sensor)
191
+ - `h`, matches number of hops
192
+ - `d`, direct, similar to `h>-1`
193
+ - `f`, flood, similar to `h<0` or `h=-1`
194
+
195
+ Commands should be written as if in interactive mode, if writing from the commandline don't forget to use commas to clearly delimit fields.
196
+
197
+ Note: Some commands like `contact_name` (aka `cn`), `reset_path` (aka `rp`), `forget_password` (aka `fp`) can be chained. There is also a `sleep` command taking an optional time parameter. The sleep will be issued after the command, it helps limiting rate through repeaters ...
198
+
199
+ #### Examples
200
+
201
+ ```
202
+ # removes all clients that have not been updated in last 2 days
203
+ at u<2d,t=1 remove_contact
204
+ # gives traces to repeaters that have been updated in the last 24h and are direct
205
+ at t=2,u>1d,d cn trace
206
+ # tries to do flood login to all repeaters
207
+ at t=2 rp login
208
+ ```
140
209
 
141
210
  ## Examples
142
211
 
@@ -15,12 +15,12 @@
15
15
 
16
16
  meshcore = python3Packages.buildPythonPackage rec {
17
17
  pname = "meshcore";
18
- version = "2.1.19";
18
+ version = "2.1.24";
19
19
  pyproject = true;
20
20
 
21
21
  src = python3Packages.fetchPypi {
22
22
  inherit pname version;
23
- sha256 = "sha256-R11puo30ozFVqsIZcbNtg/NFukm8ahFzkMVqX4XEIe0=";
23
+ sha256 = "sha256-CTn4HsVoGPij3HmHIts9Rta/iVsR8wH+CECV1vznBjQ=";
24
24
  };
25
25
 
26
26
  build-system = [python3Packages.hatchling];
@@ -57,6 +57,7 @@
57
57
  python3Packages.prompt_toolkit
58
58
  python3Packages.pyserial
59
59
  python3Packages.requests
60
+ python3Packages.pycryptodome
60
61
  ];
61
62
 
62
63
  doCheck = false;
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "meshcore-cli"
7
- version = "1.2.14"
7
+ version = "1.3.0"
8
8
  authors = [
9
9
  { name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
10
10
  ]
@@ -32,7 +32,7 @@ import re
32
32
  from meshcore import MeshCore, EventType, logger
33
33
 
34
34
  # Version
35
- VERSION = "v1.2.14"
35
+ VERSION = "v1.3.0"
36
36
 
37
37
  # default ble address is stored in a config file
38
38
  MCCLI_CONFIG_DIR = str(Path.home()) + "/.config/meshcore/"
@@ -203,29 +203,62 @@ process_event_message.print_snr=False
203
203
  process_event_message.color=True
204
204
  process_event_message.last_node=None
205
205
 
206
+ PAYLOAD_TYPENAMES = ["REQ", "RESPONSE", "TEXT_MSG", "ACK", "ADVERT", "GRP_TXT", "GRP_DATA", "ANON_REQ", "PATH", "TRACE", "MULTIPART", "CONTROL"]
207
+ ROUTE_TYPENAMES = ["TC_FLOOD", "FLOOD", "DIRECT", "TC_DIRECT"]
208
+
206
209
  async def handle_log_rx(event):
207
210
  mc = handle_log_rx.mc
208
- if handle_log_rx.json_log_rx: # json mode ... raw dump
209
- msg = json.dumps(event.payload)
210
- if handle_message.above:
211
- print_above(msg)
212
- else :
213
- print(msg)
214
- return
215
211
 
216
212
  pkt = bytes().fromhex(event.payload["payload"])
217
213
  pbuf = io.BytesIO(pkt)
218
214
  header = pbuf.read(1)[0]
215
+ route_type = header & 0x03
216
+ payload_type = (header & 0x3c) >> 2
217
+ payload_ver = (header & 0xc0) >> 6
218
+
219
+ transport_code = None
220
+ if route_type == 0x00 or route_type == 0x03: # has transport code
221
+ transport_code = pbuf.read(4) # discard transport code
222
+
223
+ path_len = pbuf.read(1)[0]
224
+ path = pbuf.read(path_len).hex() # Beware of traces where pathes are mixed
225
+
226
+ try :
227
+ route_typename = ROUTE_TYPENAMES[route_type]
228
+ except IndexError:
229
+ logger.debug(f"Unknown route type {route_type}")
230
+ route_typename = "UNK"
219
231
 
220
- if header & ~1 == 0x14: # flood msg / channel
232
+ try :
233
+ payload_typename = PAYLOAD_TYPENAMES[payload_type]
234
+ except IndexError:
235
+ logger.debug(f"Unknown payload type {payload_type}")
236
+ payload_typename = "UNK"
237
+
238
+ pkt_payload = pbuf.read()
239
+
240
+ event.payload["header"] = header
241
+ event.payload["route_type"] = route_type
242
+ event.payload["route_typename"] = route_typename
243
+ event.payload["payload_type"] = payload_type
244
+ event.payload["payload_typename"]= payload_typename
245
+
246
+ event.payload["payload_ver"] = payload_ver
247
+
248
+ if not transport_code is None:
249
+ event.payload["transport_code"] = transport_code.hex()
250
+
251
+ event.payload["path_len"] = path_len
252
+ event.payload["path"] = path
253
+
254
+ event.payload["pkt_payload"] = pkt_payload.hex()
255
+
256
+ if payload_type == 0x05: # flood msg / channel
221
257
  if handle_log_rx.channel_echoes:
222
- if header & 1 == 0: # has transport code
223
- pbuf.read(4) # discard transport code
224
- path_len = pbuf.read(1)[0]
225
- path = pbuf.read(path_len).hex()
226
- chan_hash = pbuf.read(1).hex()
227
- cipher_mac = pbuf.read(2)
228
- msg = pbuf.read() # until the end of buffer
258
+ pk_buf = io.BytesIO(pkt_payload)
259
+ chan_hash = pk_buf.read(1).hex()
260
+ cipher_mac = pk_buf.read(2)
261
+ msg = pk_buf.read() # until the end of buffer
229
262
 
230
263
  channel = None
231
264
  for c in await get_channels(mc):
@@ -258,6 +291,14 @@ async def handle_log_rx(event):
258
291
  else:
259
292
  print(txt)
260
293
 
294
+ if handle_log_rx.json_log_rx: # json mode ... raw dump
295
+ msg = json.dumps(event.payload)
296
+ if handle_message.above:
297
+ print_above(msg)
298
+ else :
299
+ print(msg)
300
+
301
+
261
302
  handle_log_rx.json_log_rx = False
262
303
  handle_log_rx.channel_echoes = False
263
304
  handle_log_rx.mc = None
@@ -1071,6 +1112,29 @@ async def process_contact_chat_line(mc, contact, line):
1071
1112
  print("")
1072
1113
  return True
1073
1114
 
1115
+ if line.startswith("sleep") or line.startswith("s"):
1116
+ try:
1117
+ sleeptime = int(line.split(" ",2)[1])
1118
+ cmd_pos = 2
1119
+ except IndexError: # nothing arg after sleep
1120
+ sleeptime = 1
1121
+ cmd_pos = 0
1122
+ except ValueError:
1123
+ sleeptime = 1
1124
+ cmd_pos = 1
1125
+
1126
+ try:
1127
+ if cmd_pos > 0:
1128
+ secline = line.split(" ",cmd_pos)[cmd_pos]
1129
+ await process_contact_chat_line(mc, contact, secline)
1130
+ except IndexError:
1131
+ pass
1132
+
1133
+ # will sleep after executed command if there is a command
1134
+ await asyncio.sleep(sleeptime)
1135
+
1136
+ return True
1137
+
1074
1138
  if line == "contact_lastmod":
1075
1139
  timestamp = contact["lastmod"]
1076
1140
  print(f"{contact['adv_name']} updated"
@@ -1723,19 +1787,7 @@ async def next_cmd(mc, cmds, json_output=False):
1723
1787
  match cmds[1]:
1724
1788
  case "help" :
1725
1789
  argnum = 1
1726
- print("""Available parameters :
1727
- pin <pin> : ble pin
1728
- radio <freq,bw,sf,cr> : radio params
1729
- tuning <rx_dly,af> : tuning params
1730
- tx <dbm> : tx power
1731
- name <name> : node name
1732
- lat <lat> : latitude
1733
- lon <lon> : longitude
1734
- coords <lat,lon> : coordinates
1735
- print_snr <on/off> : toggle snr display in messages
1736
- print_adverts <on/off> : display adverts as they come
1737
- print_new_contacts <on/off> : display new pending contacts when available
1738
- print_path_updates <on/off> : display path updates as they come""")
1790
+ get_help_for("set")
1739
1791
  case "max_flood_attempts":
1740
1792
  msg_ack.max_flood_attempts=int(cmds[2])
1741
1793
  case "max_attempts":
@@ -1959,21 +2011,7 @@ async def next_cmd(mc, cmds, json_output=False):
1959
2011
  argnum = 1
1960
2012
  match cmds[1]:
1961
2013
  case "help":
1962
- print("""Gets parameters from node
1963
- name : node name
1964
- bat : battery level in mV
1965
- fstats : fs statistics
1966
- coords : adv coordinates
1967
- lat : latitude
1968
- lon : longitude
1969
- radio : radio parameters
1970
- tx : tx power
1971
- print_snr : snr display in messages
1972
- print_adverts : display adverts as they come
1973
- print_new_contacts : display new pending contacts when available
1974
- print_path_updates : display path updates as they come
1975
- custom : all custom variables in json format
1976
- each custom var can also be get/set directly""")
2014
+ get_help_for("get")
1977
2015
  case "max_flood_attempts":
1978
2016
  if json_output :
1979
2017
  print(json.dumps({"max_flood_attempts" : msg_ack.max_flood_attempts}))
@@ -2340,6 +2378,7 @@ async def next_cmd(mc, cmds, json_output=False):
2340
2378
  else :
2341
2379
  color = process_event_message.color
2342
2380
  classic = interactive_loop.classic or not color
2381
+ print(" ", end="")
2343
2382
  for t in ev.payload["path"]:
2344
2383
  if classic :
2345
2384
  print("→",end="")
@@ -2610,15 +2649,30 @@ async def next_cmd(mc, cmds, json_output=False):
2610
2649
  if json_output:
2611
2650
  print(json.dumps(res, indent=4))
2612
2651
  else:
2652
+ width = os.get_terminal_size().columns
2613
2653
  print(f"Got {res['results_count']} neighbours out of {res['neighbours_count']} from {contact['adv_name']}:")
2614
2654
  for n in res['neighbours']:
2615
2655
  ct = mc.get_contact_by_key_prefix(n["pubkey"])
2616
- if ct :
2656
+ if ct and width > 60 :
2617
2657
  name = f"[{n['pubkey'][0:8]}] {ct['adv_name']}"
2658
+ name = f"{name:30}"
2659
+ elif ct :
2660
+ name = f"{ct['adv_name']}"
2661
+ name = f"{name:20}"
2618
2662
  else:
2619
2663
  name = f"[{n['pubkey']}]"
2620
2664
 
2621
- print(f" {name:30} last viewed {n['secs_ago']} sec ago at {n['snr']} ")
2665
+ t_s = n['secs_ago']
2666
+ time_ago = f"{t_s}s"
2667
+ if t_s / 86400 >= 1 : # result in days
2668
+ time_ago = f"{int(t_s/86400)}d ago{f' ({time_ago})' if width > 62 else ''}"
2669
+ elif t_s / 3600 >= 1 : # result in days
2670
+ time_ago = f"{int(t_s/3600)}h ago{f' ({time_ago})' if width > 62 else ''}"
2671
+ elif t_s / 60 >= 1 : # result in min
2672
+ time_ago = f"{int(t_s/60)}m ago{f' ({time_ago})' if width > 62 else ''}"
2673
+
2674
+
2675
+ print(f" {name} {time_ago}, {n['snr']}dB{' SNR' if width > 66 else ''}")
2622
2676
 
2623
2677
  case "req_binary" :
2624
2678
  argnum = 2
@@ -3068,8 +3122,8 @@ def command_help():
3068
3122
  reboot : reboots node
3069
3123
  sleep <secs> : sleeps for a given amount of secs s
3070
3124
  wait_key : wait until user presses <Enter> wk
3071
- apply_to <scope> <cmds>: sends cmds to contacts matching scope at
3072
- Messenging
3125
+ apply_to <f> <cmds> : sends cmds to contacts matching f at
3126
+ Messaging
3073
3127
  msg <name> <msg> : send message to node by name m {
3074
3128
  wait_ack : wait an ack wa }
3075
3129
  chan <nb> <msg> : send message to channel number <nb> ch
@@ -3082,6 +3136,7 @@ def command_help():
3082
3136
  get_channel <n> : get info for channel (by number or name)
3083
3137
  set_channel n nm k : set channel info (nb, name, key)
3084
3138
  remove_channel <n> : remove channel (by number or name)
3139
+ scope <s> : sets scope for flood messages
3085
3140
  Management
3086
3141
  advert : sends advert a
3087
3142
  floodadv : flood advert
@@ -3133,8 +3188,6 @@ def usage () :
3133
3188
  -D : debug
3134
3189
  -S : scan for devices and show a selector
3135
3190
  -l : list available ble/serial devices and exit
3136
- -C : toggles classic mode for prompt
3137
- -c <on/off> : disables most of color output if off
3138
3191
  -T <timeout> : timeout for the ble scan (-S and -l) default 2s
3139
3192
  -a <address> : specifies device address (can be a name)
3140
3193
  -d <name> : filter meshcore devices with name or address
@@ -3143,14 +3196,16 @@ def usage () :
3143
3196
  -p <port> : specifies tcp port (default 5000)
3144
3197
  -s <port> : use serial port <port>
3145
3198
  -b <baudrate> : specify baudrate
3199
+ -C : toggles classic mode for prompt
3200
+ -c <on/off> : disables most of color output if off
3146
3201
 
3147
3202
  Available Commands and shorcuts (can be chained) :""")
3148
3203
  command_help()
3149
3204
 
3150
3205
  def get_help_for (cmdname, context="line") :
3151
3206
  if cmdname == "apply_to" or cmdname == "at" :
3152
- print("""apply_to <scope> <cmd> : applies cmd to contacts matching scope
3153
- Scope acts like a filter with comma separated fields :
3207
+ print("""apply_to <f> <cmd> : applies cmd to contacts matching filter <f>
3208
+ Filter is constructed with comma separated fields :
3154
3209
  - u, matches modification time < or > than a timestamp
3155
3210
  (can also be days hours or minutes ago if followed by d,h or m)
3156
3211
  - t, matches the type (1: client, 2: repeater, 3: room, 4: sensor)
@@ -3158,7 +3213,7 @@ def get_help_for (cmdname, context="line") :
3158
3213
  - d, direct, similar to h>-1
3159
3214
  - f, flood, similar to h<0 or h=-1
3160
3215
 
3161
- Note: Some commands like contact_name (aka cn), reset_path (aka rp), forget_password (aka fp) can be chained.
3216
+ Note: Some commands like contact_name (aka cn), reset_path (aka rp), forget_password (aka fp) can be chained. There is also a sleep command taking an optional event. The sleep will be issued after the command, it helps limiting rate through repeaters ...
3162
3217
 
3163
3218
  Examples:
3164
3219
  # removes all clients that have not been updated in last 2 days
@@ -3169,7 +3224,7 @@ def get_help_for (cmdname, context="line") :
3169
3224
  at t=2 rp login
3170
3225
  """)
3171
3226
 
3172
- if cmdname == "node_discover" or cmdname == "nd" :
3227
+ elif cmdname == "node_discover" or cmdname == "nd" :
3173
3228
  print("""node_discover <filter> : discovers 0-hop nodes and displays signal info
3174
3229
 
3175
3230
  filter can be "all" for all types or nodes or a comma separated list consisting of :
@@ -3181,6 +3236,68 @@ def get_help_for (cmdname, context="line") :
3181
3236
  nd can be used with no filter parameter ... !!! BEWARE WITH CHAINING !!!
3182
3237
  """)
3183
3238
 
3239
+ elif cmdname == "get" :
3240
+ print("""Gets parameters from node
3241
+ Please see also help for set command, which is more up to date ...
3242
+ name : node name
3243
+ bat : battery level in mV
3244
+ fstats : fs statistics
3245
+ coords : adv coordinates
3246
+ lat : latitude
3247
+ lon : longitude
3248
+ radio : radio parameters
3249
+ tx : tx power
3250
+ print_snr : snr display in messages
3251
+ print_adverts : display adverts as they come
3252
+ print_new_contacts : display new pending contacts when available
3253
+ print_path_updates : display path updates as they come
3254
+ custom : all custom variables in json format
3255
+ each custom var can also be get/set directly""")
3256
+
3257
+ elif cmdname == "set" :
3258
+ print("""Available parameters :
3259
+ device:
3260
+ pin <pin> : ble pin
3261
+ radio <freq,bw,sf,cr> : radio params
3262
+ tuning <rx_dly,af> : tuning params
3263
+ tx <dbm> : tx power
3264
+ name <name> : node name
3265
+ lat <lat> : latitude
3266
+ lon <lon> : longitude
3267
+ coords <lat,lon> : coordinates
3268
+ auto_update_contacts <> : automatically updates contact list
3269
+ multi_ack <on/off> : multi-acks feature
3270
+ telemetry_mode_base <mode> : set basic telemetry mode all/selected/off
3271
+ telemetry_mode_loc <mode> : set location telemetry mode all/selected/off
3272
+ telemetry_mode_env <mode> : set env telemetry mode all/selected/off
3273
+ advert_loc_policy <policy> : "share" means loc will be shared in adv
3274
+ display:
3275
+ print_snr <on/off> : toggle snr display in messages
3276
+ print_adverts <on/off> : display adverts as they come
3277
+ print_new_contacts <on/off> : display new pending contacts when available
3278
+ print_path_updates <on/off> : display path updates as they come
3279
+ json_log_rx <on/off> : logs packets incoming to device as json
3280
+ channel_echoes <on/off> : print repeats for channel data
3281
+ echo_unk_channels <on/off> : also dump unk channels (encrypted)
3282
+ color <on/off> : color off should remove ANSI codes from output
3283
+ prompt:
3284
+ classic_prompt <on/off> : activates less fancier prompt
3285
+ arrow_head <string> : change arrow head in prompt
3286
+ slash_start <string> : idem for slash start
3287
+ slash_end <string> : slash end
3288
+ invert_slash <on/off> : apply color inversion to slash """)
3289
+
3290
+ elif cmdname == "scope":
3291
+ print("""scope <scope> : changes flood scope of the node
3292
+
3293
+ The scope command can be used from command line or interactive mode to set the region in which flood packets will be transmitted.
3294
+
3295
+ Managing Flood Scope in interactive mode
3296
+ Flood scope has recently been introduced in meshcore (from v1.10.0). It limits the scope of packets to regions, using transport codes in the frame.
3297
+ When entering chat mode, scope will be reset to *, meaning classic flood.
3298
+ You can switch scope using the scope command, or postfixing the to command with %<scope>.
3299
+ Scope can also be applied to a command using % before the scope name. For instance login%#Morbihan will limit diffusion of the login command (which is usually sent flood to get the path to a repeater) to the #Morbihan region.""")
3300
+
3184
3301
  else:
3185
3302
  print(f"Sorry, no help yet for {cmdname}")
3186
3303
 
File without changes
File without changes
File without changes