前提
ArduinoとM5StickCを使っています。ターミナルとはBluetooth接続です。
ターミナルからのコマンドを解析し、設定を付与した上で処理するプログラムを書いています。問題があるのはコマンドを解析するプログラムです。
実現したいこと
ターミナルから受け取った文字列をスペースによって分割し、予め定義してある構造体に入れるようプログラムしたいです。
しかし、for文内のコメントの箇所にて構造体変数に意図しない代入がされます。
ターミナルからst 1111111
と送信すると、構造体変数のコマンド名の部分には最終的に、st
が入って欲しいのですが、パラメータ値の1111111
が代入されます。
パラメータは、コマンド名 -パラメータ名 パラメータ値
でも、コマンド名 7桁の数字
でも、両方で動作してほしいので、少々回りくどい書き方のプログラムです。
該当のソースコード
arduino
1#include <M5StickC.h> 2#include <BluetoothSerial.h> 3#include "utility/MPU6886.h" 4 5#define logout SerialBT.println(__LINE__) 6 7// BT 8BluetoothSerial SerialBT; 9uint64_t chipid; 10char chipname[256] = "m5hoge"; 11 12// flags 13byte commandStatusCode = 0; 14 15// パラメータ名, パラメータ値を持ちます 16struct m5CommandParam { 17 String name, value; 18}; 19 20// コマンド名とパラメータセット(パラメータ名, パラメータ値)を持ちます 21struct m5Command { 22 String name; 23 struct m5CommandParam params[20]; 24 int paramsCount = 0; 25}; 26 27// コマンドを解析し、引数のm5Commandに解析されたコマンドのデータをセットします。 28void parseCommand(String receivedString, struct m5Command *parsedCommand) { 29 int splitedReceivedStringCount = 0; 30 String splitedReceivedString[20]; 31 receivedString.trim(); 32 33 if (receivedString.length() < 0) { // 受け取ったコマンドが空だった場合 34 commandStatusCode = 1; 35 return; 36 } 37 38 while (receivedString.length() > 0) 39 { 40 int spaceIndex = receivedString.indexOf(' '); 41 splitedReceivedStringCount++; 42 if (spaceIndex == -1) // No space found 43 { 44 splitedReceivedString[splitedReceivedStringCount - 1] = receivedString; 45 break; 46 } 47 else 48 { 49 splitedReceivedString[splitedReceivedStringCount - 1] = receivedString.substring(0, spaceIndex); 50 receivedString = receivedString.substring(spaceIndex + 1); 51 } 52 } 53 54 if (useShortCommand) { 55 bool is7digit = splitedReceivedString[1].length() == 7; 56 if (!is7digit) { 57 SerialBT.println("!is7digit"); 58 commandStatusCode = 2; 59 return; 60 } 61 62 splitedReceivedStringCount++; 63 splitedReceivedString[splitedReceivedStringCount - 1] = "-Delay"; 64 splitedReceivedString[splitedReceivedStringCount++] = splitedReceivedString[1].substring(0, 3); 65 66 splitedReceivedString[splitedReceivedStringCount++] = "-ShouldGetAccelAdc"; 67 splitedReceivedString[splitedReceivedStringCount++] = splitedReceivedString[1][3]; 68 69 splitedReceivedString[splitedReceivedStringCount++] = "-Afs"; 70 splitedReceivedString[splitedReceivedStringCount++] = splitedReceivedString[1][4]; 71 72 splitedReceivedString[splitedReceivedStringCount++] = "-ShouldGetGyroAdc"; 73 splitedReceivedString[splitedReceivedStringCount++] = splitedReceivedString[1][5]; 74 75 splitedReceivedString[splitedReceivedStringCount++] = "-Gfs"; 76 splitedReceivedString[splitedReceivedStringCount++] = splitedReceivedString[1][6]; 77 } 78 79 // 空白によって区切られた文字列をm5Commandに変換する 80 parsedCommand->name = splitedReceivedString[0]; // この時点でparsedCommand->nameは'st' 81 82 // todo: debug 83 SerialBT.printf("Debug: Line: '"); 84 logout; 85 SerialBT.printf("parsedCommand.name: '"); 86 SerialBT.print(parsedCommand->name); 87 SerialBT.printf("'"); 88 SerialBT.println(""); 89 90 for (int i = 1; i < splitedReceivedStringCount; i++) { 91 // todo: debug 92 SerialBT.printf("Debug: Line: '"); 93 logout; 94 SerialBT.printf("i: '"); 95 SerialBT.print(i); 96 SerialBT.printf("', "); 97 SerialBT.printf("parsedCommand.name: '"); 98 SerialBT.print(parsedCommand->name);//ここではstと出力される 99 SerialBT.printf("'"); 100 SerialBT.println(""); 101 bool isParamName = splitedReceivedString[i][0] == '-'; 102 if (isParamName) { 103 parsedCommand->paramsCount++; 104 parsedCommand->params[parsedCommand->paramsCount - 1].name = splitedReceivedString[i]; 105 } else { 106 parsedCommand->params[parsedCommand->paramsCount - 1].value = splitedReceivedString[i]; //問題のか所。この行を消すとparsedCommand->nameは'st'のままだが、残すとi:1の際にparsedCommand->nameが1111111となる。 107 } 108 } 109 110 // todo: debug 111 SerialBT.printf("Debug: Line: '"); 112 logout; 113 SerialBT.printf("parsedCommand.name: '"); 114 SerialBT.print(parsedCommand->name); // ここで1111111と出力されるが、stと出力されるのを想定している。 115 SerialBT.printf("'"); 116 SerialBT.println(""); 117 SerialBT.printf("parsedCommand.paramsCount: '"); 118 SerialBT.print((String)parsedCommand->paramsCount); 119 SerialBT.printf("'"); 120 SerialBT.println(""); 121} 122 123// シリアルから送られてきたコマンドを実行する 124void executeCommandFromSerial() { 125 if (SerialBT.available() > 0) { // バッファにデータがある場合 126 receivedFromTerminal = SerialBT.readStringUntil('\r'); // ターミナルから送信された文字列をCRの手前まで取得 127 SerialBT.println(receivedFromTerminal); 128 if (receivedFromTerminal.isEmpty()) { 129 SerialBT.println("isEmpty"); // todo: remove 130 commandStatusCode = 1; 131 return; 132 } 133 134 // コマンドを解析する 135 struct m5Command parsedCommand; 136 parseCommand(receivedFromTerminal, &parsedCommand); 137 } 138} 139 140void setup() { 141 // M5 142 M5.begin(); 143 M5.Lcd.setRotation(3); 144 M5.Lcd.fillScreen(BLACK); 145 M5.Lcd.printf("Bluetooth: %s\n", chipname); 146 sensorInit(); 147 148 //BT 149 chipid = ESP.getEfuseMac(); 150 SerialBT.begin(chipname); 151 SerialBT.setTimeout(10 * 1000); 152} 153 154void loop() { 155 executeCommandFromSerial(); 156}

回答2件
あなたの回答
tips
プレビュー