aranea-sdk-cli 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AraneaSDK Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # @aranea-sdk/cli
2
+
3
+ AraneaSDK CLI - ESP32 IoTデバイス開発支援ツール
4
+
5
+ ## 概要
6
+
7
+ AraneaSDK CLIは、AraneaSDK対応ESP32デバイスの開発・テスト・登録を支援するコマンドラインツールです。
8
+
9
+ ## インストール
10
+
11
+ ```bash
12
+ npm install -g @aranea-sdk/cli
13
+ ```
14
+
15
+ ## クイックスタート
16
+
17
+ ```bash
18
+ # 接続テスト
19
+ aranea-sdk test connection --endpoint production
20
+
21
+ # 認証テスト (テストテナント)
22
+ aranea-sdk test auth
23
+
24
+ # デバイス登録 (ドライラン)
25
+ aranea-sdk register --type aranea_ar-is04a --mac AABBCCDDEEFF --dry-run
26
+
27
+ # スキーマ取得
28
+ aranea-sdk schema get --type aranea_ar-is04a
29
+ ```
30
+
31
+ ## コマンド一覧
32
+
33
+ ### test - 接続・認証テスト
34
+
35
+ ```bash
36
+ # API接続テスト
37
+ aranea-sdk test connection [--endpoint production|staging]
38
+
39
+ # 認証テスト (テストテナント使用)
40
+ aranea-sdk test auth
41
+
42
+ # カスタム認証情報でテスト
43
+ aranea-sdk test auth --tid T123... --lacis-id 173... --cic 022029
44
+ ```
45
+
46
+ ### register - デバイス登録
47
+
48
+ ```bash
49
+ # ドライラン (登録せずに検証)
50
+ aranea-sdk register --type aranea_ar-is04a --mac AABBCCDDEEFF --dry-run
51
+
52
+ # 実登録 (テストテナント)
53
+ aranea-sdk register --type aranea_ar-is04a --mac AABBCCDDEEFF
54
+
55
+ # カスタムテナントに登録
56
+ aranea-sdk register \
57
+ --type aranea_ar-is04a \
58
+ --mac AABBCCDDEEFF \
59
+ --tid T999... \
60
+ --lacis-id 173... \
61
+ --cic 022029
62
+ ```
63
+
64
+ #### オプション
65
+
66
+ | オプション | 説明 | デフォルト |
67
+ |-----------|------|-----------|
68
+ | `-t, --type` | デバイスType (必須) | - |
69
+ | `-m, --mac` | MACアドレス 12桁HEX (必須) | - |
70
+ | `--tid` | テナントID | テストテナント |
71
+ | `--lacis-id` | 登録者LacisID | テストテナント |
72
+ | `--cic` | 登録者CIC | テストテナント |
73
+ | `-d, --dry-run` | 検証のみ | false |
74
+ | `-e, --endpoint` | 環境 | production |
75
+
76
+ ### schema - スキーマ操作
77
+
78
+ ```bash
79
+ # スキーマ取得
80
+ aranea-sdk schema get --type aranea_ar-is04a
81
+
82
+ # スキーマ検証
83
+ aranea-sdk schema validate --file state.json --type aranea_ar-is04a
84
+ ```
85
+
86
+ ### validate - Type名検証
87
+
88
+ ```bash
89
+ # Type名検証
90
+ aranea-sdk validate type --type aranea_ar-is04a
91
+
92
+ # レガシーType名検証 (ISMS_ar-*)
93
+ aranea-sdk validate type --type ISMS_ar-is04a
94
+ ```
95
+
96
+ ### simulate - 状態レポートシミュレーション
97
+
98
+ ```bash
99
+ # ファイルからシミュレーション
100
+ aranea-sdk simulate state-report --file test.json --dry-run
101
+
102
+ # JSONペイロード直接指定
103
+ aranea-sdk simulate state-report --payload '{"temp": 25.5}'
104
+ ```
105
+
106
+ ## 対応デバイスType
107
+
108
+ | Type | ProductType | 説明 |
109
+ |------|-------------|------|
110
+ | `aranea_ar-is01` | 001 | AraneaSDK Basic Sensor |
111
+ | `aranea_ar-is04a` | 004 | Network Scanner (ESP32) |
112
+ | `aranea_ar-is05a` | 005 | Environment Sensor (ESP32) |
113
+ | `aranea_ar-is06a` | 006 | Power Monitor (ESP32) |
114
+ | `aranea_ar-is10` | 010 | Router Inspector (OpenWrt/AsusWRT) |
115
+
116
+ ## LacisID生成規則
117
+
118
+ AraneaDeviceのLacisIDは以下の形式で自動生成されます:
119
+
120
+ ```
121
+ [Prefix][ProductType][MAC][ProductCode] = 20文字
122
+
123
+ Prefix: 3 (araneaDevice固定)
124
+ ProductType: 3桁 (例: 004)
125
+ MAC: 12桁HEX (例: AABBCCDDEEFF)
126
+ ProductCode: 4桁4進数 (枝番から算出)
127
+ ```
128
+
129
+ **例**: `aranea_ar-is04a` + MAC `AABBCCDDEEFF`
130
+ → LacisID: `3004AABBCCDDEEFF1201`
131
+
132
+ ## 環境設定
133
+
134
+ | 環境 | Gate API | State API |
135
+ |-----|----------|-----------|
136
+ | production | `asia-northeast1-mobesorder.cloudfunctions.net` | 同左 |
137
+ | staging | `asia-northeast1-mobesorder-staging.cloudfunctions.net` | 同左 |
138
+
139
+ ## テストテナント
140
+
141
+ 開発・テスト用に以下のテストテナントが利用可能です:
142
+
143
+ - **TID**: `T9999999999999999999`
144
+ - **Email**: `dev@araneadevice.dev`
145
+
146
+ テストテナントを使用する場合、`--tid`, `--lacis-id`, `--cic` オプションは省略可能です。
147
+
148
+ ## レガシーType名サポート
149
+
150
+ `ISMS_ar-*` プレフィックスは永続的にサポートされます:
151
+
152
+ ```bash
153
+ # ISMS_ar-* は aranea_ar-* に自動変換
154
+ aranea-sdk register --type ISMS_ar-is04a --mac AABBCCDDEEFF
155
+ # → typeWarning.suggestedType: "aranea_ar-is04a" で登録
156
+ ```
157
+
158
+ ## 要件
159
+
160
+ - Node.js >= 18.0.0
161
+
162
+ ## ライセンス
163
+
164
+ MIT License - see [LICENSE](./LICENSE)
165
+
166
+ ## 関連リンク
167
+
168
+ - [AraneaSDK Documentation](https://github.com/warusakudeveroper/mobes2.0/tree/main/doc/APPS/araneaSDK)
169
+ - [Issues](https://github.com/warusakudeveroper/mobes2.0/issues)
@@ -0,0 +1,9 @@
1
+ /**
2
+ * register コマンド
3
+ *
4
+ * Usage:
5
+ * aranea-sdk register --type "aranea_ar-is04a" --mac "AABBCCDDEEFF" --dry-run
6
+ * aranea-sdk register --type "aranea_ar-is04a" --mac "AABBCCDDEEFF" --tid T999... --lacis-id 173... --cic 022029
7
+ */
8
+ import { Command } from 'commander';
9
+ export declare const registerCommand: Command;
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * register コマンド
4
+ *
5
+ * Usage:
6
+ * aranea-sdk register --type "aranea_ar-is04a" --mac "AABBCCDDEEFF" --dry-run
7
+ * aranea-sdk register --type "aranea_ar-is04a" --mac "AABBCCDDEEFF" --tid T999... --lacis-id 173... --cic 022029
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.registerCommand = void 0;
14
+ const commander_1 = require("commander");
15
+ const chalk_1 = __importDefault(require("chalk"));
16
+ const ora_1 = __importDefault(require("ora"));
17
+ const node_fetch_1 = __importDefault(require("node-fetch"));
18
+ const config_1 = require("../config");
19
+ // ProductType mapping
20
+ const PRODUCT_TYPE_MAP = {
21
+ 'aranea_ar-is01': '001',
22
+ 'aranea_ar-is04a': '004',
23
+ 'aranea_ar-is05a': '005',
24
+ 'aranea_ar-is06a': '006',
25
+ 'aranea_ar-is10': '010',
26
+ };
27
+ /**
28
+ * 枝番アルファベット → ASCII → 4進数変換
29
+ */
30
+ function suffixToProductCode(suffix) {
31
+ if (!suffix)
32
+ return '0001'; // デフォルト
33
+ const char = suffix.charAt(0);
34
+ const ascii = char.charCodeAt(0);
35
+ // ASCII を 4進数に変換 (各2ビット)
36
+ const d0 = (ascii >> 6) & 0x03;
37
+ const d1 = (ascii >> 4) & 0x03;
38
+ const d2 = (ascii >> 2) & 0x03;
39
+ const d3 = ascii & 0x03;
40
+ return `${d0}${d1}${d2}${d3}`;
41
+ }
42
+ /**
43
+ * Type名からProductType と枝番を抽出
44
+ */
45
+ function parseType(type) {
46
+ // aranea_ar-is04a → productType: 004, suffix: a
47
+ const match = type.match(/^aranea_ar-is(\d{2})([a-z])?$/);
48
+ if (match) {
49
+ return {
50
+ productType: match[1].padStart(3, '0'),
51
+ suffix: match[2],
52
+ };
53
+ }
54
+ // フォールバック: マッピングテーブルから取得
55
+ const productType = PRODUCT_TYPE_MAP[type];
56
+ if (productType) {
57
+ return { productType };
58
+ }
59
+ throw new Error(`Unknown type: ${type}`);
60
+ }
61
+ /**
62
+ * LacisID生成 (deviceWithMAC形式)
63
+ * Format: [Prefix][ProductType][MAC][ProductCode] = 20文字
64
+ */
65
+ function generateLacisId(productType, mac, productCode) {
66
+ const prefix = '3'; // araneaDevice
67
+ const cleanMac = mac.replace(/[:\-]/g, '').toUpperCase();
68
+ if (cleanMac.length !== 12) {
69
+ throw new Error(`Invalid MAC length: ${cleanMac.length} (expected 12)`);
70
+ }
71
+ return `${prefix}${productType}${cleanMac}${productCode}`;
72
+ }
73
+ exports.registerCommand = new commander_1.Command('register')
74
+ .description('デバイス登録 (ドライラン / 実登録)')
75
+ .requiredOption('-t, --type <type>', 'デバイスType (例: aranea_ar-is04a)')
76
+ .requiredOption('-m, --mac <mac>', 'MACアドレス (12桁HEX)')
77
+ .option('--tid <tid>', 'テナントID', config_1.TEST_TENANT.tid)
78
+ .option('--lacis-id <lacisId>', 'Tenant Primary LacisID', config_1.TEST_TENANT.primaryLacisId)
79
+ .option('--user-id <userId>', 'Tenant Primary Email', config_1.TEST_TENANT.primaryEmail)
80
+ .option('--cic <cic>', 'Tenant Primary CIC', config_1.TEST_TENANT.primaryCic)
81
+ .option('-d, --dry-run', '実際には登録せず、リクエスト内容を検証')
82
+ .option('-e, --endpoint <env>', '環境 (production/staging)', 'production')
83
+ .action(async (options) => {
84
+ try {
85
+ console.log(chalk_1.default.bold('\n=== デバイス登録 ===\n'));
86
+ // Type解析
87
+ const { productType, suffix } = parseType(options.type);
88
+ const productCode = suffixToProductCode(suffix);
89
+ // MAC正規化
90
+ const cleanMac = options.mac.replace(/[:\-]/g, '').toUpperCase();
91
+ // LacisID生成
92
+ const deviceLacisId = generateLacisId(productType, cleanMac, productCode);
93
+ console.log(chalk_1.default.cyan('デバイス情報:'));
94
+ console.log(` Type: ${options.type}`);
95
+ console.log(` ProductType: ${productType}`);
96
+ console.log(` ProductCode: ${productCode}`);
97
+ console.log(` MAC: ${cleanMac}`);
98
+ console.log(` LacisID: ${deviceLacisId}`);
99
+ console.log('');
100
+ // リクエストボディ構築
101
+ const requestBody = {
102
+ lacisOath: {
103
+ lacisId: options.lacisId,
104
+ userId: options.userId,
105
+ cic: options.cic,
106
+ method: 'register',
107
+ },
108
+ userObject: {
109
+ lacisID: deviceLacisId,
110
+ tid: options.tid,
111
+ typeDomain: 'araneaDevice',
112
+ type: options.type,
113
+ },
114
+ deviceMeta: {
115
+ macAddress: cleanMac,
116
+ productType: productType,
117
+ productCode: productCode,
118
+ },
119
+ };
120
+ console.log(chalk_1.default.cyan('リクエスト内容:'));
121
+ // CICをマスク
122
+ const maskedBody = {
123
+ ...requestBody,
124
+ lacisOath: {
125
+ ...requestBody.lacisOath,
126
+ cic: requestBody.lacisOath.cic.substring(0, 2) + '****',
127
+ },
128
+ };
129
+ console.log(JSON.stringify(maskedBody, null, 2));
130
+ console.log('');
131
+ if (options.dryRun) {
132
+ console.log(chalk_1.default.yellow('(dry-run モード: 実際には登録されません)'));
133
+ console.log('');
134
+ // バリデーションのみ実行
135
+ console.log(chalk_1.default.cyan('バリデーション結果:'));
136
+ // LacisID長チェック
137
+ if (deviceLacisId.length !== 20) {
138
+ console.log(chalk_1.default.red(` ✗ LacisID長エラー: ${deviceLacisId.length}桁 (期待: 20桁)`));
139
+ }
140
+ else {
141
+ console.log(chalk_1.default.green(' ✓ LacisID形式: 正常'));
142
+ }
143
+ // MAC形式チェック
144
+ if (!/^[0-9A-F]{12}$/.test(cleanMac)) {
145
+ console.log(chalk_1.default.red(` ✗ MACアドレス形式エラー`));
146
+ }
147
+ else {
148
+ console.log(chalk_1.default.green(' ✓ MACアドレス形式: 正常'));
149
+ }
150
+ // ProductCode形式チェック (4進数)
151
+ if (!/^[0-3]{4}$/.test(productCode)) {
152
+ console.log(chalk_1.default.yellow(` ⚠ ProductCode形式: 4進数以外 (${productCode})`));
153
+ }
154
+ else {
155
+ console.log(chalk_1.default.green(` ✓ ProductCode形式: 4進数 (${productCode})`));
156
+ }
157
+ // Prefix チェック
158
+ if (deviceLacisId[0] !== '3') {
159
+ console.log(chalk_1.default.red(` ✗ Prefix エラー: ${deviceLacisId[0]} (期待: 3)`));
160
+ }
161
+ else {
162
+ console.log(chalk_1.default.green(' ✓ Prefix: 3 (araneaDevice)'));
163
+ }
164
+ console.log('');
165
+ console.log(chalk_1.default.green('✓ ドライラン完了 - 形式チェック通過'));
166
+ console.log('');
167
+ console.log(chalk_1.default.gray('実際に登録するには --dry-run オプションを外してください'));
168
+ console.log('');
169
+ return;
170
+ }
171
+ // 実登録
172
+ const spinner = (0, ora_1.default)('デバイス登録中...').start();
173
+ const endpoint = (0, config_1.getEndpoint)(options.endpoint);
174
+ const response = await (0, node_fetch_1.default)(endpoint.gate, {
175
+ method: 'POST',
176
+ headers: { 'Content-Type': 'application/json' },
177
+ body: JSON.stringify(requestBody),
178
+ });
179
+ const result = (await response.json());
180
+ spinner.stop();
181
+ console.log(chalk_1.default.cyan('レスポンス:'));
182
+ console.log(JSON.stringify(result, null, 2));
183
+ console.log('');
184
+ if (result.ok) {
185
+ console.log(chalk_1.default.green('✓ デバイス登録成功'));
186
+ console.log('');
187
+ console.log(` デバイスLacisID: ${result.lacisId || deviceLacisId}`);
188
+ console.log(` デバイスCIC: ${result.userObject?.cic_code || '(発行済)'}`);
189
+ if (result.stateEndpoint) {
190
+ console.log('');
191
+ console.log(chalk_1.default.cyan('状態レポート送信先:'));
192
+ console.log(` ${result.stateEndpoint}`);
193
+ }
194
+ if (result.mqttEndpoint) {
195
+ console.log('');
196
+ console.log(chalk_1.default.cyan('MQTT接続先:'));
197
+ console.log(` ${result.mqttEndpoint}`);
198
+ }
199
+ if (result.typeWarning) {
200
+ console.log('');
201
+ console.log(chalk_1.default.yellow('⚠ Type警告:'));
202
+ console.log(` 受信Type: ${result.typeWarning.receivedType}`);
203
+ console.log(` 推奨Type: ${result.typeWarning.suggestedType}`);
204
+ }
205
+ }
206
+ else {
207
+ console.log(chalk_1.default.red('✗ デバイス登録失敗'));
208
+ console.log(` エラー: ${result.error}`);
209
+ if (result.error?.includes('MAC') || result.error?.includes('duplicate')) {
210
+ console.log('');
211
+ console.log(chalk_1.default.yellow('ヒント: 同一MACアドレスのデバイスが既に登録されている可能性があります'));
212
+ }
213
+ }
214
+ console.log('');
215
+ }
216
+ catch (error) {
217
+ console.error(chalk_1.default.red(`エラー: ${error.message}`));
218
+ process.exit(1);
219
+ }
220
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * schema コマンド
3
+ *
4
+ * Usage:
5
+ * aranea-sdk schema get --type "aranea_ar-is04a"
6
+ * aranea-sdk schema list
7
+ */
8
+ import { Command } from 'commander';
9
+ export declare const schemaCommand: Command;