| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <limits.h> |
| #include "os/mynewt.h" |
| #include "console/console.h" |
| #include "shell/shell.h" |
| #include "parse/parse.h" |
| #include "node/lora_priv.h" |
| #include "node/lora.h" |
| |
| extern void |
| lora_app_shell_txd_func(uint8_t port, LoRaMacEventInfoStatus_t status, |
| Mcps_t pkt_type, struct os_mbuf *om); |
| |
| extern void |
| lora_app_shell_rxd_func(uint8_t port, LoRaMacEventInfoStatus_t status, |
| Mcps_t pkt_type, struct os_mbuf *om); |
| |
| extern void |
| lora_app_shell_join_cb(LoRaMacEventInfoStatus_t status, uint8_t attempts); |
| |
| extern void |
| lora_app_shell_link_chk_cb(LoRaMacEventInfoStatus_t status, uint8_t num_gw, |
| uint8_t demod_margin); |
| |
| #define LORA_APP_SHELL_MAX_APP_PAYLOAD (250) |
| static uint8_t las_cmd_app_tx_buf[LORA_APP_SHELL_MAX_APP_PAYLOAD]; |
| |
| struct mib_pair { |
| char *mib_name; |
| Mib_t mib_param; |
| }; |
| |
| static struct mib_pair lora_mib[] = { |
| {"device_class", MIB_DEVICE_CLASS}, |
| {"nwk_joined", MIB_NETWORK_JOINED}, |
| {"adr", MIB_ADR}, |
| {"net_id", MIB_NET_ID}, |
| {"dev_addr", MIB_DEV_ADDR}, |
| {"nwk_skey", MIB_NWK_SKEY}, |
| {"app_skey", MIB_APP_SKEY}, |
| {"pub_nwk", MIB_PUBLIC_NETWORK}, |
| {"repeater", MIB_REPEATER_SUPPORT}, |
| {"rx2_chan", MIB_RX2_CHANNEL}, |
| {"rx2_def_chan", MIB_RX2_DEFAULT_CHANNEL}, |
| {"chan_mask", MIB_CHANNELS_MASK}, |
| {"chan_def_mask", MIB_CHANNELS_DEFAULT_MASK}, |
| {"chan_nb_rep", MIB_CHANNELS_NB_REP}, |
| {"max_rx_win_dur", MIB_MAX_RX_WINDOW_DURATION}, |
| {"rx_delay1", MIB_RECEIVE_DELAY_1}, |
| {"rx_delay2", MIB_RECEIVE_DELAY_2}, |
| {"join_acc_delay1", MIB_JOIN_ACCEPT_DELAY_1}, |
| {"join_acc_delay2", MIB_JOIN_ACCEPT_DELAY_2}, |
| {"chan_dr", MIB_CHANNELS_DATARATE}, |
| {"chan_def_dr", MIB_CHANNELS_DEFAULT_DATARATE}, |
| {"chan_tx_pwr", MIB_CHANNELS_TX_POWER}, |
| {"chan_def_tx_pwr", MIB_CHANNELS_DEFAULT_TX_POWER}, |
| {"uplink_cntr", MIB_UPLINK_COUNTER}, |
| {"downlink_cntr", MIB_DOWNLINK_COUNTER}, |
| {"multicast_chan", MIB_MULTICAST_CHANNEL}, |
| {"sys_max_rx_err", MIB_SYSTEM_MAX_RX_ERROR}, |
| {"min_rx_symbols", MIB_MIN_RX_SYMBOLS}, |
| {NULL, (Mib_t)0} |
| }; |
| |
| static int las_cmd_wr_mib(int argc, char **argv); |
| static int las_cmd_rd_mib(int argc, char **argv); |
| static int las_cmd_wr_dev_eui(int argc, char **argv); |
| static int las_cmd_rd_dev_eui(int argc, char **argv); |
| static int las_cmd_wr_app_eui(int argc, char **argv); |
| static int las_cmd_rd_app_eui(int argc, char **argv); |
| static int las_cmd_wr_app_key(int argc, char **argv); |
| static int las_cmd_rd_app_key(int argc, char **argv); |
| static int las_cmd_app_port(int argc, char **argv); |
| static int las_cmd_app_tx(int argc, char **argv); |
| static int las_cmd_join(int argc, char **argv); |
| static int las_cmd_link_chk(int argc, char **argv); |
| |
| static struct shell_cmd las_cmds[] = { |
| { |
| .sc_cmd = "las_wr_mib", |
| .sc_cmd_func = las_cmd_wr_mib, |
| }, |
| { |
| .sc_cmd = "las_rd_mib", |
| .sc_cmd_func = las_cmd_rd_mib, |
| }, |
| { |
| .sc_cmd = "las_rd_dev_eui", |
| .sc_cmd_func = las_cmd_rd_dev_eui, |
| }, |
| { |
| .sc_cmd = "las_wr_dev_eui", |
| .sc_cmd_func = las_cmd_wr_dev_eui, |
| }, |
| { |
| .sc_cmd = "las_rd_app_eui", |
| .sc_cmd_func = las_cmd_rd_app_eui, |
| }, |
| { |
| .sc_cmd = "las_wr_app_eui", |
| .sc_cmd_func = las_cmd_wr_app_eui, |
| }, |
| { |
| .sc_cmd = "las_rd_app_key", |
| .sc_cmd_func = las_cmd_rd_app_key, |
| }, |
| { |
| .sc_cmd = "las_wr_app_key", |
| .sc_cmd_func = las_cmd_wr_app_key, |
| }, |
| { |
| .sc_cmd = "las_app_port", |
| .sc_cmd_func = las_cmd_app_port, |
| }, |
| { |
| .sc_cmd = "las_app_tx", |
| .sc_cmd_func = las_cmd_app_tx, |
| }, |
| { |
| .sc_cmd = "las_join", |
| .sc_cmd_func = las_cmd_join, |
| }, |
| { |
| .sc_cmd = "las_link_chk", |
| .sc_cmd_func = las_cmd_link_chk, |
| }, |
| { |
| NULL, NULL, |
| #if MYNEWT_VAL(SHELL_CMD_HELP) |
| NULL |
| #endif |
| }, |
| }; |
| |
| #define LAS_NUM_CLI_CMDS (sizeof las_cmds / sizeof las_cmds[0]) |
| |
| void |
| las_cmd_disp_byte_str(uint8_t *bytes, int len) |
| { |
| int i; |
| |
| if (len > 0) { |
| for (i = 0; i < len - 1; ++i) { |
| console_printf("%02x:", bytes[i]); |
| } |
| console_printf("%02x\n", bytes[len - 1]); |
| } |
| } |
| |
| static void |
| las_cmd_disp_chan_mask(uint16_t *mask) |
| { |
| uint16_t i; |
| uint16_t len; |
| uint16_t max_chans; |
| PhyParam_t phy_param; |
| GetPhyParams_t getPhy; |
| |
| if (!mask) { |
| return; |
| } |
| |
| getPhy.Attribute = PHY_MAX_NB_CHANNELS; |
| phy_param = RegionGetPhyParam(LORA_NODE_REGION, &getPhy); |
| max_chans = phy_param.Value; |
| |
| len = max_chans / 16; |
| if ((len * 16) != max_chans) { |
| len += 1; |
| } |
| |
| for (i = 0; i < len - 1; ++i) { |
| console_printf("%04x:", mask[i]); |
| } |
| console_printf("%04x\n", mask[len - 1]); |
| } |
| |
| /** |
| * Display list of MAC mibs |
| * |
| */ |
| static void |
| las_cmd_show_mibs(void) |
| { |
| struct mib_pair *mp; |
| |
| mp = &lora_mib[0]; |
| while (mp->mib_name != NULL) { |
| console_printf("%s\n", mp->mib_name); |
| ++mp; |
| } |
| } |
| |
| static struct mib_pair * |
| las_find_mib_by_name(char *mibname) |
| { |
| struct mib_pair *mp; |
| |
| mp = &lora_mib[0]; |
| while (mp->mib_name != NULL) { |
| if (!strcmp(mibname, mp->mib_name)) { |
| return mp; |
| } |
| ++mp; |
| } |
| |
| return NULL; |
| } |
| |
| static void |
| las_cmd_wr_mib_help(void) |
| { |
| console_printf("las_wr_mib <mib_name> <val> where mib_name is one of:\n"); |
| las_cmd_show_mibs(); |
| } |
| |
| static int |
| las_parse_bool(char *str) |
| { |
| int rc; |
| |
| if (!strcmp(str, "0")) { |
| rc = 0; |
| } else if (!strcmp(str, "1")) { |
| rc = 1; |
| } else { |
| console_printf("Invalid value. Valid values are 0 or 1\n"); |
| rc = -1; |
| } |
| |
| return rc; |
| } |
| |
| static int |
| las_cmd_wr_mib(int argc, char **argv) |
| { |
| int rc; |
| int plen; |
| uint8_t key[LORA_KEY_LEN]; |
| uint16_t mask[16]; |
| int mask_len; |
| struct mib_pair *mp; |
| MibRequestConfirm_t mib; |
| GetPhyParams_t getPhy; |
| PhyParam_t phy_param; |
| |
| if (argc < 3) { |
| console_printf("Invalid # of arguments\n"); |
| goto wr_mib_err; |
| } |
| |
| if (strcmp(argv[1], "help") == 0) { |
| las_cmd_wr_mib_help(); |
| return 0; |
| } |
| |
| mp = las_find_mib_by_name(argv[1]); |
| if (mp == NULL) { |
| console_printf("No mib named %s\n",argv[1]); |
| goto wr_mib_err; |
| } |
| |
| /* parse value */ |
| mib.Type = mp->mib_param; |
| switch (mib.Type) { |
| case MIB_DEVICE_CLASS: |
| if (!strcmp(argv[2], "A")) { |
| mib.Param.Class = CLASS_A; |
| } else if (!strcmp(argv[2], "B")) { |
| console_printf("Class B devices currently not supported\n"); |
| return 0; |
| } else if (!strcmp(argv[2], "C")) { |
| mib.Param.Class = CLASS_C; |
| } else { |
| console_printf("Invalid value. Valid values are A, B or C\n"); |
| return 0; |
| } |
| break; |
| case MIB_NETWORK_JOINED: |
| rc = las_parse_bool(argv[2]); |
| if (rc == 0) { |
| mib.Param.IsNetworkJoined = false; |
| } else if (rc == 1) { |
| mib.Param.IsNetworkJoined = true; |
| } else { |
| return 0; |
| } |
| break; |
| case MIB_ADR: |
| rc = las_parse_bool(argv[2]); |
| if (rc == 0) { |
| mib.Param.AdrEnable = false; |
| } else if (rc == 1) { |
| mib.Param.AdrEnable = true; |
| } else { |
| return 0; |
| } |
| break; |
| case MIB_NET_ID: |
| mib.Param.NetID = (uint32_t)parse_ull(argv[2], &rc); |
| if (rc) { |
| console_printf("Unable to parse value\n"); |
| return 0; |
| } |
| break; |
| case MIB_DEV_ADDR: |
| mib.Param.DevAddr = (uint32_t)parse_ull(argv[2], &rc); |
| if (rc) { |
| console_printf("Unable to parse value\n"); |
| return 0; |
| } |
| break; |
| case MIB_NWK_SKEY: |
| rc = parse_byte_stream(argv[2], LORA_KEY_LEN, key, &plen); |
| if (rc || (plen != LORA_KEY_LEN)) { |
| console_printf("Key does not parse. Must be 16 bytes" |
| " and separated by : or -\n"); |
| return 0; |
| } |
| mib.Param.NwkSKey = key; |
| break; |
| case MIB_APP_SKEY: |
| rc = parse_byte_stream(argv[2], LORA_KEY_LEN, key, &plen); |
| if (rc || (plen != LORA_KEY_LEN)) { |
| console_printf("Key does not parse. Must be 16 bytes" |
| " and separated by : or -\n"); |
| return 0; |
| } |
| mib.Param.AppSKey = key; |
| break; |
| case MIB_PUBLIC_NETWORK: |
| rc = las_parse_bool(argv[2]); |
| if (rc == 0) { |
| mib.Param.EnablePublicNetwork = false; |
| } else if (rc == 1) { |
| mib.Param.EnablePublicNetwork = true; |
| } else { |
| return 0; |
| } |
| break; |
| case MIB_REPEATER_SUPPORT: |
| rc = las_parse_bool(argv[2]); |
| if (rc == 0) { |
| mib.Param.EnableRepeaterSupport = false; |
| } else if (rc == 1) { |
| mib.Param.EnableRepeaterSupport = true; |
| } else { |
| return 0; |
| } |
| break; |
| case MIB_CHANNELS: |
| //mib.Param.ChannelList; |
| break; |
| case MIB_RX2_CHANNEL: |
| //mib.Param.Rx2Channel; |
| break; |
| case MIB_RX2_DEFAULT_CHANNEL: |
| //mib.Param.Rx2Channel; |
| break; |
| case MIB_CHANNELS_DEFAULT_MASK: |
| /* NOTE: fall-through intentional */ |
| case MIB_CHANNELS_MASK: |
| memset(mask, 0, sizeof(mask)); |
| |
| getPhy.Attribute = PHY_MAX_NB_CHANNELS; |
| phy_param = RegionGetPhyParam(LORA_NODE_REGION, &getPhy); |
| mask_len = phy_param.Value / 8; |
| if ((mask_len * 8) != phy_param.Value) { |
| mask_len += 1; |
| } |
| |
| /* NOTE: re-use of key here for temp buffer storage */ |
| rc = parse_byte_stream(argv[2], mask_len, key, &plen); |
| if (rc || (plen != mask_len)) { |
| console_printf("Mask does not parse. Must be %d bytes" |
| " and separated by : or -\n", mask_len); |
| return 0; |
| } |
| |
| /* construct mask from byte stream */ |
| rc = 0; |
| for (plen = 0; plen < mask_len; plen += 2) { |
| mask[rc] = key[plen]; |
| if ((mask_len & 1) == 0) { |
| mask[rc] += ((uint16_t)key[plen + 1]) << 8; |
| } |
| ++rc; |
| } |
| |
| if (mib.Type == MIB_CHANNELS_DEFAULT_MASK) { |
| mib.Param.ChannelsDefaultMask = mask; |
| } else { |
| mib.Param.ChannelsMask = mask; |
| } |
| break; |
| case MIB_CHANNELS_NB_REP: |
| //mib.Param.ChannelNbRep; |
| break; |
| case MIB_MAX_RX_WINDOW_DURATION: |
| //mib.Param.MaxRxWindow; |
| break; |
| case MIB_RECEIVE_DELAY_1: |
| //mib.Param.ReceiveDelay1; |
| break; |
| case MIB_RECEIVE_DELAY_2: |
| //mib.Param.ReceiveDelay2; |
| break; |
| case MIB_JOIN_ACCEPT_DELAY_1: |
| //mib.Param.JoinAcceptDelay1; |
| break; |
| case MIB_JOIN_ACCEPT_DELAY_2: |
| //mib.Param.JoinAcceptDelay2; |
| break; |
| case MIB_CHANNELS_DEFAULT_DATARATE: |
| mib.Param.ChannelsDefaultDatarate = parse_ll(argv[2], &rc); |
| if (rc) { |
| console_printf("Unable to parse value\n"); |
| return 0; |
| } |
| break; |
| case MIB_CHANNELS_DATARATE: |
| mib.Param.ChannelsDatarate = parse_ll(argv[2], &rc); |
| if (rc) { |
| console_printf("Unable to parse value\n"); |
| return 0; |
| } |
| break; |
| case MIB_CHANNELS_DEFAULT_TX_POWER: |
| //mibGet.Param.ChannelsDefaultTxPower; |
| break; |
| case MIB_CHANNELS_TX_POWER: |
| //mib.Param.ChannelsTxPower; |
| break; |
| case MIB_UPLINK_COUNTER: |
| //mib.Param.UpLinkCounter; |
| break; |
| case MIB_DOWNLINK_COUNTER: |
| //mib.Param.DownLinkCounter; |
| break; |
| case MIB_MULTICAST_CHANNEL: |
| //mib.Param.MulticastList = MulticastChannels; |
| break; |
| default: |
| assert(0); |
| break; |
| } |
| |
| if (LoRaMacMibSetRequestConfirm(&mib) != LORAMAC_STATUS_OK) { |
| console_printf("Mib not able to be set\n"); |
| return 0; |
| } |
| |
| console_printf("mib %s set\n", mp->mib_name); |
| |
| return 0; |
| |
| wr_mib_err: |
| las_cmd_wr_mib_help(); |
| return 0; |
| } |
| |
| static void |
| las_cmd_rd_mib_help(void) |
| { |
| console_printf("las_rd_mib <mib_name> where mib_name is one of:\n"); |
| las_cmd_show_mibs(); |
| } |
| |
| static int |
| las_cmd_rd_mib(int argc, char **argv) |
| { |
| struct mib_pair *mp; |
| LoRaMacStatus_t stat; |
| MibRequestConfirm_t mibGet; |
| |
| if (argc != 2) { |
| console_printf("Invalid # of arguments\n"); |
| goto rd_mib_err; |
| } |
| |
| if (strcmp(argv[1], "help") == 0) { |
| las_cmd_rd_mib_help(); |
| return 0; |
| } |
| |
| mp = las_find_mib_by_name(argv[1]); |
| if (mp == NULL) { |
| console_printf("No mib named %s\n",argv[1]); |
| goto rd_mib_err; |
| } |
| |
| /* Read the mib value */ |
| mibGet.Type = mp->mib_param; |
| stat = LoRaMacMibGetRequestConfirm(&mibGet); |
| if (stat != LORAMAC_STATUS_OK) { |
| console_printf("Mib lookup failure\n"); |
| goto rd_mib_err; |
| } |
| |
| console_printf("%s=", mp->mib_name); |
| /* Display the value */ |
| switch (mibGet.Type) { |
| case MIB_DEVICE_CLASS: |
| console_printf("%c\n", 'A' + mibGet.Param.Class); |
| break; |
| case MIB_NETWORK_JOINED: |
| console_printf("%d\n", mibGet.Param.IsNetworkJoined); |
| break; |
| case MIB_ADR: |
| console_printf("%d\n", mibGet.Param.AdrEnable); |
| break; |
| case MIB_NET_ID: |
| console_printf("%08lx\n", mibGet.Param.NetID); |
| break; |
| case MIB_DEV_ADDR: |
| console_printf("%08lx\n", mibGet.Param.DevAddr); |
| break; |
| case MIB_NWK_SKEY: |
| las_cmd_disp_byte_str(mibGet.Param.NwkSKey, LORA_KEY_LEN); |
| break; |
| case MIB_APP_SKEY: |
| las_cmd_disp_byte_str(mibGet.Param.AppSKey, LORA_KEY_LEN); |
| break; |
| case MIB_PUBLIC_NETWORK: |
| console_printf("%d\n", mibGet.Param.EnablePublicNetwork); |
| break; |
| case MIB_REPEATER_SUPPORT: |
| console_printf("%d\n", mibGet.Param.EnableRepeaterSupport); |
| break; |
| case MIB_CHANNELS: |
| //mibGet.Param.ChannelList; |
| break; |
| case MIB_RX2_CHANNEL: |
| //mibGet.Param.Rx2Channel; |
| break; |
| case MIB_RX2_DEFAULT_CHANNEL: |
| //mibGet.Param.Rx2Channel; |
| break; |
| case MIB_CHANNELS_DEFAULT_MASK: |
| las_cmd_disp_chan_mask(mibGet.Param.ChannelsDefaultMask); |
| break; |
| case MIB_CHANNELS_MASK: |
| las_cmd_disp_chan_mask(mibGet.Param.ChannelsMask); |
| break; |
| case MIB_CHANNELS_NB_REP: |
| console_printf("%u\n", mibGet.Param.ChannelNbRep); |
| break; |
| case MIB_MAX_RX_WINDOW_DURATION: |
| console_printf("%lu\n", mibGet.Param.MaxRxWindow); |
| break; |
| case MIB_RECEIVE_DELAY_1: |
| console_printf("%lu\n", mibGet.Param.ReceiveDelay1); |
| break; |
| case MIB_RECEIVE_DELAY_2: |
| console_printf("%lu\n", mibGet.Param.ReceiveDelay2); |
| break; |
| case MIB_JOIN_ACCEPT_DELAY_1: |
| console_printf("%lu\n", mibGet.Param.JoinAcceptDelay1); |
| break; |
| case MIB_JOIN_ACCEPT_DELAY_2: |
| console_printf("%lu\n", mibGet.Param.JoinAcceptDelay2); |
| break; |
| case MIB_CHANNELS_DEFAULT_DATARATE: |
| console_printf("%d\n", mibGet.Param.ChannelsDefaultDatarate); |
| break; |
| case MIB_CHANNELS_DATARATE: |
| console_printf("%d\n", mibGet.Param.ChannelsDatarate); |
| break; |
| case MIB_CHANNELS_DEFAULT_TX_POWER: |
| console_printf("%d\n", mibGet.Param.ChannelsDefaultTxPower); |
| break; |
| case MIB_CHANNELS_TX_POWER: |
| console_printf("%d\n", mibGet.Param.ChannelsTxPower); |
| break; |
| case MIB_UPLINK_COUNTER: |
| console_printf("%lu\n", mibGet.Param.UpLinkCounter); |
| break; |
| case MIB_DOWNLINK_COUNTER: |
| console_printf("%lu\n", mibGet.Param.DownLinkCounter); |
| break; |
| case MIB_MULTICAST_CHANNEL: |
| //mibGet.Param.MulticastList = MulticastChannels; |
| break; |
| default: |
| assert(0); |
| break; |
| } |
| return 0; |
| |
| rd_mib_err: |
| las_cmd_rd_mib_help(); |
| return 0; |
| } |
| |
| static int |
| las_cmd_rd_dev_eui(int argc, char **argv) |
| { |
| if (argc != 1) { |
| console_printf("Invalid # of arguments. Usage: las_rd_dev_eui\n"); |
| return 0; |
| } |
| |
| las_cmd_disp_byte_str(g_lora_dev_eui, LORA_EUI_LEN); |
| return 0; |
| } |
| |
| static int |
| las_cmd_wr_dev_eui(int argc, char **argv) |
| { |
| int rc; |
| int plen; |
| uint8_t eui[LORA_EUI_LEN]; |
| |
| if (argc < 2) { |
| console_printf("Invalid # of arguments." |
| " Usage: las_wr_dev_eui <xx:xx:xx:xx:xx:xx:xx:xx>\n"); |
| } |
| |
| rc = parse_byte_stream(argv[1], LORA_EUI_LEN, eui, &plen); |
| if (rc || (plen != LORA_EUI_LEN)) { |
| console_printf("EUI does not parse. Must be 8 bytes" |
| " and separated by : or -\n"); |
| } else { |
| memcpy(g_lora_dev_eui, eui, LORA_EUI_LEN); |
| } |
| |
| return 0; |
| } |
| |
| static int |
| las_cmd_rd_app_eui(int argc, char **argv) |
| { |
| if (argc != 1) { |
| console_printf("Invalid # of arguments. Usage: las_rd_app_eui\n"); |
| return 0; |
| } |
| |
| las_cmd_disp_byte_str(g_lora_app_eui, LORA_EUI_LEN); |
| return 0; |
| } |
| |
| static int |
| las_cmd_wr_app_eui(int argc, char **argv) |
| { |
| int rc; |
| int plen; |
| uint8_t eui[LORA_EUI_LEN]; |
| |
| if (argc < 2) { |
| console_printf("Invalid # of arguments." |
| " Usage: las_wr_app_eui <xx:xx:xx:xx:xx:xx:xx:xx>\n"); |
| } |
| |
| rc = parse_byte_stream(argv[1], LORA_EUI_LEN, eui, &plen); |
| if (rc || (plen != LORA_EUI_LEN)) { |
| console_printf("EUI does not parse. Must be 8 bytes" |
| " and separated by : or -\n"); |
| } else { |
| memcpy(g_lora_app_eui, eui, LORA_EUI_LEN); |
| } |
| |
| return 0; |
| } |
| |
| static int |
| las_cmd_rd_app_key(int argc, char **argv) |
| { |
| if (argc != 1) { |
| console_printf("Invalid # of arguments. Usage: las_rd_app_key\n"); |
| return 0; |
| } |
| |
| las_cmd_disp_byte_str(g_lora_app_key, LORA_KEY_LEN); |
| return 0; |
| } |
| |
| static int |
| las_cmd_wr_app_key(int argc, char **argv) |
| { |
| int rc; |
| int plen; |
| uint8_t key[LORA_KEY_LEN]; |
| |
| if (argc < 2) { |
| console_printf("Invalid # of arguments." |
| " Usage: las_wr_app_key <xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" |
| ":xx:xx:xx:xx:xx:xx\n"); |
| } |
| |
| rc = parse_byte_stream(argv[1], LORA_KEY_LEN, key, &plen); |
| if (rc || (plen != LORA_KEY_LEN)) { |
| console_printf("Key does not parse. Must be 16 bytes and separated by" |
| " : or -\n"); |
| return 0; |
| } else { |
| memcpy(g_lora_app_key, key, LORA_KEY_LEN); |
| } |
| |
| return 0; |
| } |
| |
| static int |
| las_cmd_app_port(int argc, char **argv) |
| { |
| int rc; |
| uint8_t port; |
| uint8_t retries; |
| |
| if (argc < 3) { |
| console_printf("Invalid # of arguments.\n"); |
| goto cmd_app_port_err; |
| } |
| |
| port = parse_ull_bounds(argv[2], 1, 255, &rc); |
| if (rc != 0) { |
| console_printf("Invalid port %s. Must be 1 - 255\n", argv[2]); |
| return 0; |
| } |
| |
| if (!strcmp(argv[1], "open")) { |
| rc = lora_app_port_open(port, lora_app_shell_txd_func, |
| lora_app_shell_rxd_func); |
| if (rc == LORA_APP_STATUS_OK) { |
| console_printf("Opened app port %u\n", port); |
| } else { |
| console_printf("Failed to open app port %u err=%d\n", port, rc); |
| } |
| } else if (!strcmp(argv[1], "close")) { |
| rc = lora_app_port_close(port); |
| if (rc == LORA_APP_STATUS_OK) { |
| console_printf("Closed app port %u\n", port); |
| } else { |
| console_printf("Failed to close app port %u err=%d\n", port, rc); |
| } |
| } else if (!strcmp(argv[1], "cfg")) { |
| if (argc != 4) { |
| console_printf("Invalid # of arguments.\n"); |
| goto cmd_app_port_err; |
| } |
| retries = parse_ull_bounds(argv[3], 1, MAX_ACK_RETRIES, &rc); |
| if (rc) { |
| console_printf("Invalid # of retries. Must be between 1 and " |
| "%d (inclusve)\n", MAX_ACK_RETRIES); |
| return 0; |
| } |
| |
| rc = lora_app_port_cfg(port, retries); |
| if (rc == LORA_APP_STATUS_OK) { |
| console_printf("App port %u configured w/retries=%u\n", |
| port, retries); |
| } else { |
| console_printf("Cannot configure port %u err=%d\n", port, rc); |
| } |
| } else if (!strcmp(argv[1], "show")) { |
| if (rc == LORA_APP_STATUS_OK) { |
| console_printf("app port %u\n", port); |
| /* XXX: implement */ |
| } else { |
| console_printf("Cannot show app port %u err=%d\n", port, rc); |
| } |
| } else { |
| console_printf("Invalid port command.\n"); |
| goto cmd_app_port_err; |
| } |
| |
| return 0; |
| |
| cmd_app_port_err: |
| console_printf("Usage:\n"); |
| console_printf("\tlas_app_port open <port num>\n"); |
| console_printf("\tlas_app_port close <port num>\n"); |
| console_printf("\tlas_app_port cfg <port num> <retries>\n"); |
| console_printf("\not implemented! las_app_port show <port num | all>\n"); |
| return 0; |
| } |
| |
| static int |
| las_cmd_app_tx(int argc, char **argv) |
| { |
| int rc; |
| uint8_t port; |
| uint8_t len; |
| uint8_t pkt_type; |
| struct os_mbuf *om; |
| Mcps_t mcps_type; |
| |
| if (argc < 4) { |
| console_printf("Invalid # of arguments\n"); |
| goto cmd_app_tx_err; |
| } |
| |
| port = parse_ull_bounds(argv[1], 1, 255, &rc); |
| if (rc != 0) { |
| console_printf("Invalid port %s. Must be 1 - 255\n", argv[2]); |
| return 0; |
| } |
| len = parse_ull_bounds(argv[2], 1, LORA_APP_SHELL_MAX_APP_PAYLOAD, &rc); |
| if (rc != 0) { |
| console_printf("Invalid length. Must be 1 - %u\n", |
| LORA_APP_SHELL_MAX_APP_PAYLOAD); |
| return 0; |
| } |
| pkt_type = parse_ull_bounds(argv[3], 0, 1, &rc); |
| if (rc != 0) { |
| console_printf("Invalid type. Must be 0 (unconfirmed) or 1 (confirmed)" |
| "\n"); |
| return 0; |
| } |
| |
| if (lora_app_mtu() < len) { |
| console_printf("Can send at max %d bytes\n", lora_app_mtu()); |
| return 0; |
| } |
| |
| /* Attempt to allocate a mbuf */ |
| om = lora_pkt_alloc(); |
| if (!om) { |
| console_printf("Unable to allocate mbuf\n"); |
| return 0; |
| } |
| |
| /* Get correct packet type. */ |
| if (pkt_type == 0) { |
| mcps_type = MCPS_UNCONFIRMED; |
| } else { |
| mcps_type = MCPS_CONFIRMED; |
| } |
| |
| rc = os_mbuf_copyinto(om, 0, las_cmd_app_tx_buf, len); |
| assert(rc == 0); |
| |
| rc = lora_app_port_send(port, mcps_type, om); |
| if (rc) { |
| console_printf("Failed to send to port %u err=%d\n", port, rc); |
| os_mbuf_free_chain(om); |
| } else { |
| console_printf("Packet sent on port %u\n", port); |
| } |
| |
| return 0; |
| |
| cmd_app_tx_err: |
| console_printf("Usage:\n"); |
| console_printf("\tlas_app_tx <port> <len> <type>\n"); |
| console_printf("Where:\n"); |
| console_printf("\tport = port number on which to send\n"); |
| console_printf("\tlen = size n bytes of app data\n"); |
| console_printf("\ttype = 0 for unconfirmed, 1 for confirmed\n"); |
| console_printf("\tex: las_app_tx 10 20 1\n"); |
| |
| return 0; |
| } |
| |
| static int |
| las_cmd_link_chk(int argc, char **argv) |
| { |
| int rc; |
| |
| rc = lora_app_link_check(); |
| if (rc) { |
| console_printf("Link check start failure err=%d\n", rc); |
| } else { |
| console_printf("Sending link check\n"); |
| } |
| return 0; |
| } |
| |
| static int |
| las_cmd_join(int argc, char **argv) |
| { |
| int rc; |
| uint8_t attempts; |
| |
| /* Get the number of attempts */ |
| if (argc != 2) { |
| console_printf("Invalid # of arguments\n"); |
| goto cmd_join_err; |
| } |
| |
| attempts = parse_ull_bounds(argv[1], 0, 255, &rc); |
| if (rc) { |
| console_printf("Error: could not parse attempts. Must be 0 - 255\n"); |
| |
| } |
| |
| rc = lora_app_join(g_lora_dev_eui, g_lora_app_eui, g_lora_app_key,attempts); |
| if (rc) { |
| console_printf("Join attempt start failure err=%d\n", rc); |
| } else { |
| console_printf("Attempting to join...\n"); |
| } |
| return 0; |
| |
| cmd_join_err: |
| console_printf("Usage:\n"); |
| console_printf("\tlas_join <attempts>\n"); |
| console_printf("Where:\n"); |
| console_printf("\tattempts = # of join requests to send before failure" |
| " (0 -255)ß\n"); |
| console_printf("\tex: las_join 10\n"); |
| return 0; |
| } |
| |
| void |
| las_cmd_init(void) |
| { |
| int i; |
| int rc; |
| |
| /* Set the join callback */ |
| lora_app_set_join_cb(lora_app_shell_join_cb); |
| |
| /* Set link check callback */ |
| lora_app_set_link_check_cb(lora_app_shell_link_chk_cb); |
| |
| for (i = 0; i < LAS_NUM_CLI_CMDS; i++) { |
| rc = shell_cmd_register(las_cmds + i); |
| SYSINIT_PANIC_ASSERT_MSG( |
| rc == 0, "Failed to register lora app shell CLI commands"); |
| } |
| |
| /* Init app tx payload to incrementing pattern */ |
| for (i = 0; i < LORA_APP_SHELL_MAX_APP_PAYLOAD; ++i) { |
| las_cmd_app_tx_buf[i] = i; |
| } |
| } |