Exemplo n.º 1
0
/****************************************************************************
 *
 * NAME: cbvMcRxHandler
 *
 * DESCRIPTION:
 *
 * RETURNS:
 *
 ****************************************************************************/
PUBLIC void cbToCoNet_vRxEvent(tsRxDataApp *pRx) {
	int i;

	// print coming payload
	V_PRINTF(
			"\n\r[PKT Ad:%04x,Ln:%03d,Seq:%03d,Lq:%03d,Tms:%05d \"",
			pRx->u32SrcAddr, pRx->u8Len, // Actual payload byte: the network layer uses additional 4 bytes.
			pRx->u8Seq, pRx->u8Lqi, pRx->u32Tick & 0xFFFF);

	for (i = 0; i < pRx->u8Len; i++) {
		if (i < 32) {
			V_PUTCHAR((pRx->auData[i] >= 0x20 && pRx->auData[i] <= 0x7f) ?
							pRx->auData[i] : '.');
		} else {
			V_PRINTF( "..");
			break;
		}
	}
	V_PRINTF( "\"]");

	// 直接受信したパケットを上位へ転送する
	if (pRx->auData[0] == 'T') {
		tsTxDataApp sTx;
		memset(&sTx, 0, sizeof(sTx));

		sTx.u32DstAddr = TOCONET_NWK_ADDR_PARENT;
		sTx.u32SrcAddr = ToCoNet_u32GetSerial(); // Transmit using Long address
		sTx.u8Cmd = 0; // data packet.

		sTx.u8Seq = pRx->u8Seq;
		sTx.u8CbId = pRx->u8Seq;

		sTx.u16DelayMax = 300; // 送信開始の遅延を大きめに設定する

		memcpy(sTx.auData, pRx->auData, pRx->u8Len);
		sTx.auData[0] = 'R';
		sTx.u8Len = pRx->u8Len;

#ifdef USE_AES
		sTx.bSecurePacket = TRUE;
#endif

		SPRINTF_vRewind();
		vfPrintf(SPRINTF_Stream, ":%03d", pRx->u8Lqi);

		memcpy(sTx.auData + sTx.u8Len, SPRINTF_pu8GetBuff(), SPRINTF_u16Length());
		sTx.u8Len += SPRINTF_u16Length();

		ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx);
	}
}
/**
 * アプリケーション再送
 *
 * @param E_STATE_APP_RETRY_TX
 * @param pEv
 * @param eEvent
 * @param u32evarg
 */
PRSEV_HANDLER_DEF(E_STATE_APP_RETRY_TX, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
	// 遷移してきたとき
	if (eEvent == E_EVENT_NEW_STATE) {
		if (ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx_Retry)) {
			V_PRINTF(LB"TxOk");
			ToCoNet_Tx_vProcessQueue(); // 送信処理をタイマーを待たずに実行する
			ToCoNet_Event_SetState(pEv, E_STATE_APP_WAIT_TX);
		} else {
			V_PRINTF(LB"TxFl");
			ToCoNet_Event_SetState(pEv, E_STATE_APP_RETRY);
		}

		V_PRINTF(" FR=%04X", sAppData.u16frame_count);
	}
}
Exemplo n.º 3
0
PRSEV_HANDLER_DEF(E_STATE_APP_WAIT_TX, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
	if (eEvent == E_EVENT_NEW_STATE) {
		// 暗号化鍵の登録
		if (IS_APPCONF_OPT_SECURE()) {
			bool_t bRes = bRegAesKey(sAppData.sFlash.sData.u32EncKey);
			V_PRINTF(LB "*** Register AES key (%d) ***", bRes);
		}

		// ネットワークの初期化
		if (!sAppData.pContextNwk) {
			// 初回のみ
			sAppData.sNwkLayerTreeConfig.u8Role = TOCONET_NWK_ROLE_ENDDEVICE;
			sAppData.pContextNwk = ToCoNet_NwkLyTr_psConfig_MiniNodes(&sAppData.sNwkLayerTreeConfig);
			if (sAppData.pContextNwk) {
				ToCoNet_Nwk_bInit(sAppData.pContextNwk);
				ToCoNet_Nwk_bStart(sAppData.pContextNwk);
			} else {
				ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // スリープ状態へ遷移
				return;
			}
		} else {
			// 一度初期化したら RESUME
			ToCoNet_Nwk_bResume(sAppData.pContextNwk);
		}

		// 初期化後速やかに送信要求
		V_PRINTF(LB"[SNS_COMP/TX]");
		sAppData.u16frame_count++; // シリアル番号を更新する

		tsTxDataApp sTx;
		memset(&sTx, 0, sizeof(sTx)); // 必ず0クリアしてから使う!
		uint8 *q =  sTx.auData;

		sTx.u32SrcAddr = ToCoNet_u32GetSerial();

		if (IS_APPCONF_OPT_TO_ROUTER()) {
			// ルータがアプリ中で一度受信して、ルータから親機に再配送
			sTx.u32DstAddr = TOCONET_NWK_ADDR_NEIGHBOUR_ABOVE;
		} else {
			// ルータがアプリ中では受信せず、単純に中継する
			sTx.u32DstAddr = TOCONET_NWK_ADDR_PARENT;
		}

		// ペイロードの準備
		S_OCTET('T');
		S_OCTET(sAppData.sFlash.sData.u8id);
		S_BE_WORD(sAppData.u16frame_count);

		S_OCTET(PKT_ID_LIS3DH); // パケット識別子

		S_OCTET(sAppData.sSns.u8Batt);
		S_BE_WORD(sAppData.sSns.u16Adc1);
		S_BE_WORD(sAppData.sSns.u16Adc2);
		S_BE_WORD(sObjLIS3DH.ai16Result[LIS3DH_IDX_X]);
		S_BE_WORD(sObjLIS3DH.ai16Result[LIS3DH_IDX_Y]);
		S_BE_WORD(sObjLIS3DH.ai16Result[LIS3DH_IDX_Z]);

		/*	DIの入力状態を取得	*/
		uint8 DI_Bitmap = readInput();
		S_OCTET( DI_Bitmap );

		sTx.u8Len = q - sTx.auData; // パケットのサイズ
		sTx.u8CbId = sAppData.u16frame_count & 0xFF; // TxEvent で通知される番号、送信先には通知されない
		sTx.u8Seq = sAppData.u16frame_count & 0xFF; // シーケンス番号(送信先に通知される)
		sTx.u8Cmd = 0; // 0..7 の値を取る。パケットの種別を分けたい時に使用する
		//sTx.u8Retry = 0x81; // 強制2回送信

		if (IS_APPCONF_OPT_SECURE()) {
			sTx.bSecurePacket = TRUE;
		}

		if (ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx)) {
			V_PRINTF(LB"TxOk");
			ToCoNet_Tx_vProcessQueue(); // 送信処理をタイマーを待たずに実行する
		} else {
			V_PRINTF(LB"TxFl");
			ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // 送信失敗
		}

		V_PRINTF(" FR=%04X", sAppData.u16frame_count);
	}

	if (eEvent == E_ORDER_KICK) { // 送信完了イベントが来たのでスリープする
		ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // スリープ状態へ遷移
	}

	// タイムアウト
	if (ToCoNet_Event_u32TickFrNewState(pEv) > 100) {
		V_PRINTF(LB"! TIME OUT (E_STATE_APP_WAIT_TX)");
		ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // スリープ状態へ遷移
	}
}
/**
 * UART コマンド待ち
 * @param E_STATE_RUNNING
 * @param pEv
 * @param eEvent
 * @param u32evarg
 */
PRSEV_HANDLER_DEF(E_STATE_RUNNING, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
	if (eEvent == E_EVENT_NEW_STATE) {
		uint8 au8msg[16], *q = au8msg;

		V_PRINTF(LB "[RUNNING]");
		V_FLUSH();

		// 起動メッセージとしてシリアル番号を出力する
		S_BE_DWORD(ToCoNet_u32GetSerial());
		sSerCmdOut.au8data = au8msg;
		sSerCmdOut.u16len = q - au8msg;

		sSerCmdOut.vOutput(&sSerCmdOut, &sSerStream);
	} else
#if 0
	if (!bPortRead(DIO_BUTTON)) {
		// DIO_BUTTON が Hi に戻ったらスリープに戻す
		ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP);
	} else
#endif
	if (eEvent == E_ORDER_KICK) {
		// UARTのコマンドが入力されるまで待って、送信
		tsSerCmd_Context *pCmd = NULL;
		if (u32evarg) {
			pCmd = (void*)u32evarg;
		}

		if (pCmd && pCmd->u16len <= 80) {
			; // この場合は処理する
		} else {
			ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP);
			return;
		}

		V_PRINTF(LB"[RUNNING/UARTRECV ln=%d]", pCmd->u16len);
		sAppData.u16frame_count++; // シリアル番号を更新する

		tsTxDataApp sTx;
		memset(&sTx, 0, sizeof(sTx)); // 必ず0クリアしてから使う!
		uint8 *q =  sTx.auData;

		sTx.u32SrcAddr = ToCoNet_u32GetSerial();

		if (IS_APPCONF_OPT_TO_ROUTER()) {
			// ルータがアプリ中で一度受信して、ルータから親機に再配送
			sTx.u32DstAddr = TOCONET_NWK_ADDR_NEIGHBOUR_ABOVE;
		} else {
			// ルータがアプリ中では受信せず、単純に中継する
			sTx.u32DstAddr = TOCONET_NWK_ADDR_PARENT;
		}

		// ペイロードの準備
		S_OCTET('T');
		S_OCTET(sAppData.sFlash.sData.u8id);
		S_BE_WORD(sAppData.u16frame_count);

		S_OCTET(PKT_ID_UART); // パケット識別子
		S_OCTET(pCmd->u16len); // ペイロードサイズ
		memcpy(q, pCmd->au8data, pCmd->u16len); // データ部
		q += pCmd->u16len;

		sTx.u8Len = q - sTx.auData; // パケットのサイズ
		sTx.u8CbId = sAppData.u16frame_count & 0xFF; // TxEvent で通知される番号、送信先には通知されない
		sTx.u8Seq = sAppData.u16frame_count & 0xFF; // シーケンス番号(送信先に通知される)
		sTx.u8Cmd = 0; // 0..7 の値を取る。パケットの種別を分けたい時に使用する
		//sTx.u8Retry = 0x81; // 強制2回送信

		if (IS_APPCONF_OPT_SECURE()) {
			sTx.bSecurePacket = TRUE;
		}

		if (ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx)) {
			V_PRINTF(LB"TxOk");
			ToCoNet_Tx_vProcessQueue(); // 送信処理をタイマーを待たずに実行する
			ToCoNet_Event_SetState(pEv, E_STATE_APP_WAIT_TX);
		} else {
			V_PRINTF(LB"TxFl");
			ToCoNet_Event_SetState(pEv, E_STATE_APP_RETRY);
		}

		if (bRetry) {
			sTx_Retry = sTx;
		}

		V_PRINTF(" FR=%04X", sAppData.u16frame_count);
	}

	// タイムアウト(期待の時間までにデータが来なかった)
	if (ToCoNet_Event_u32TickFrNewState(pEv) > sAppData.sFlash.sData.u32Slp) {
		V_PRINTF(LB"! TIME OUT (E_STATE_RUNNING)");
		ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // スリープ状態へ遷移
	}
}
Exemplo n.º 5
0
/****************************************************************************
 *
 * NAME: cbvMcRxHandler
 *
 * DESCRIPTION:
 *
 * RETURNS:
 *
 ****************************************************************************/
PUBLIC void cbToCoNet_vRxEvent(tsRxDataApp *pRx) {
	int i;

	// print coming payload
	V_PRINTF(
			LB "[PKT Ad:%04x,Ln:%03d,Seq:%03d,Lq:%03d,Tms:%05d %s\"",
			pRx->u32SrcAddr, pRx->u8Len, // Actual payload byte: the network layer uses additional 4 bytes.
			pRx->u8Seq, pRx->u8Lqi, pRx->u32Tick & 0xFFFF, pRx->bSecurePkt ? "Enc " : "");

	for (i = 0; i < pRx->u8Len; i++) {
		if (i < 32) {
			V_PUTCHAR((pRx->auData[i] >= 0x20 && pRx->auData[i] <= 0x7f) ?
							pRx->auData[i] : '.');
		} else {
			V_PRINTF( "..");
			break;
		}
	}
	V_PRINTF( "\"]");

	// 暗号化対応時に平文パケットは受信しない
	if (IS_APPCONF_OPT_SECURE()) {
		if (!pRx->bSecurePkt) {
			V_PRINTF( ".. skipped plain packet.");
			return;
		}
	}

	// 直接受信したパケットを上位へ転送する
	//
	// 直接親機宛(TOCONET_NWK_ADDR_PARENT指定で送信)に向けたパケットはここでは処理されない。
	// 本処理はアドレス指定がTOCONET_NWK_ADDR_NEIGHBOUR_ABOVEの場合で、一端中継機が受け取り
	// その中継機のアドレス、受信時のLQIを含めて親機に伝達する方式である。
	if (pRx->auData[0] == 'T') {
		tsTxDataApp sTx;
		memset(&sTx, 0, sizeof(sTx));
		uint8 *q = sTx.auData;

		S_OCTET('R'); // 1バイト目に中継機フラグを立てる
		S_BE_DWORD(pRx->u32SrcAddr); // 子機のアドレスを
		S_OCTET(pRx->u8Lqi); // 受信したLQI を保存する

		memcpy(sTx.auData + 6, pRx->auData + 1, pRx->u8Len - 1); // 先頭の1バイトを除いて5バイト先にコピーする
		q += pRx->u8Len - 1;

		sTx.u8Len = q - sTx.auData;

		sTx.u32DstAddr = TOCONET_NWK_ADDR_PARENT;
		sTx.u32SrcAddr = ToCoNet_u32GetSerial(); // Transmit using Long address
		sTx.u8Cmd = 0; // data packet.

		sTx.u8Seq = pRx->u8Seq;
		sTx.u8CbId = pRx->u8Seq;

		sTx.u16DelayMax = 300; // 送信開始の遅延を大きめに設定する


		if (IS_APPCONF_OPT_SECURE()) {
			sTx.bSecurePacket = TRUE;
		}

		ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx);
	}
}
/*	パケットを送信する状態	*/
PRSEV_HANDLER_DEF(E_STATE_RUNNING, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
	if (eEvent == E_EVENT_NEW_STATE) {
		// ADC の開始
		vADC_WaitInit();
		vSnsObj_Process(&sAppData.sADC, E_ORDER_KICK);
	}
	if (eEvent == E_ORDER_KICK) {
		V_PRINTF(LB"[E_STATE_RUNNING/SNS_COMP]");
		sAppData.u16frame_count++; // シリアル番号を更新する

		tsTxDataApp sTx;
		memset(&sTx, 0, sizeof(sTx)); // 必ず0クリアしてから使う!
		uint8 *q =  sTx.auData;

		sTx.u32SrcAddr = ToCoNet_u32GetSerial();

		sTx.u16DelayMin = 0;
		sTx.u16DelayMax = 0;
		sTx.u16RetryDur = 0;
		sTx.u8Retry = 0;

		if (IS_APPCONF_OPT_TO_ROUTER()) {
			// ルータがアプリ中で一度受信して、ルータから親機に再配送
			sTx.u32DstAddr = TOCONET_NWK_ADDR_NEIGHBOUR_ABOVE;
		} else {
			// ルータがアプリ中では受信せず、単純に中継する
			sTx.u32DstAddr = TOCONET_NWK_ADDR_PARENT;
		}

		// ペイロードの準備
		S_OCTET('T');
		S_OCTET(sAppData.sFlash.sData.u8id);
		S_BE_WORD(sAppData.u16frame_count);

		S_OCTET(sAppData.sFlash.sData.u8mode);	// パケット識別子

		S_OCTET(sAppData.sSns.u8Batt);

		S_BE_WORD(sAppData.sSns.u16Adc1);
		S_BE_WORD(sAppData.sSns.u16Adc2);

		//	立ち上がりで起動 or 立ち下がりで起動
		if( sAppData.sFlash.sData.i16param == 1 ){
			S_OCTET(0x01);
		} else {
			S_OCTET(0x00);
		}

		/*	DIの入力状態を取得	*/
		uint8 DI_Bitmap = readInput();
		S_OCTET( DI_Bitmap );
		sAppData.bDI1_Now_Opened = ((DI_Bitmap & 1) == 0);


		sTx.u8Len = q - sTx.auData; // パケットのサイズ
		sTx.u8CbId = sAppData.u16frame_count & 0xFF; // TxEvent で通知される番号、送信先には通知されない
		sTx.u8Seq = sAppData.u16frame_count & 0xFF; // シーケンス番号(送信先に通知される)
		sTx.u8Cmd = 0; // 0..7 の値を取る。パケットの種別を分けたい時に使用する
		//sTx.u8Retry = 0x81; // 強制2回送信

		if (IS_APPCONF_OPT_SECURE()) {
			sTx.bSecurePacket = TRUE;
		}

		if (ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx)) {
			V_PRINTF(LB"TxOk");
			ToCoNet_Tx_vProcessQueue(); // 送信処理をタイマーを待たずに実行する
			ToCoNet_Event_SetState(pEv, E_STATE_APP_WAIT_TX);
		} else {
			V_PRINTF(LB"TxFl");
			ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP);
		}
		V_PRINTF(" FR=%04X", sAppData.u16frame_count);
	}
}