烟感器设备接入AWS IOT的一种方法(二)

AWS 上的 Demo server 停掉了,为此做个记录,以备后查。

借助AWS 官方的 IOT core sdk 可以模拟设备(假设是烟感器)进行TLS认证,和加密通讯数据。

方法一:借助Mqtt.fx 工具连接到AWS IOT core 平台上 。

获取设备端的 crt, 加密公钥和私钥,以及root.CA 具体方法参见“烟感器设备接入AWS IOT的一种方法(一)”  以下给出结果:

=====新增注意事项======

1.给证书附加策略的时候,需要注意:mqtt.fx 不是AWS设备,策略对应的权限需要放宽:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:*",
      "Resource": "*"
    }
  ]
}

===========

将上述文件下载到本地一个目录,然后倒入到mqtt.fx 中

mqtt.fx 进行connected 后,发送消息给IOT core ,IOT core端可以收到信息:

==========================================================================

方法二:将 aws-iot-device-sdk-embedded-C-master  安装在Ubuntu 上,如Mqtt.fx一样做相关连接配置后,可以连接到AWS IOT core 平台上 :(sdk的部分code : shadow_sample.c)

/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 */

/**
 * @file shadow_sample.c
 * @brief A simple connected window example demonstrating the use of Thing Shadow
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>

#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_shadow_interface.h"

/*!
 * The goal of this sample application is to demonstrate the capabilities of shadow.
 * This device(say Connected Window) will open the window of a room based on temperature
 * It can report to the Shadow the following parameters:
 *  1. temperature of the room (double)
 *  2. status of the window (open or close)
 * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close]
 *
 * The two variables from a device's perspective are double temperature and bool windowOpen
 * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback    
 The Json Document in the cloud will be
 {
 "reported": {
 "temperature": 0,
 "windowOpen": false
 },
 "desired": {
 "windowOpen": false
 }
 }
 */
 /*   新的jason格式
 {
  "reported": {
    "ProductLifeCycle": 10000,
    "SmokeErrState": 0,
    "SmokeAlertFlag": 0,
    "CODensity": 0,
    "BatteryCapacity": 100,
    "SmokeMuteFlag": 0
  }
}
*/

#define ROOMTEMPERATURE_UPPERLIMIT 32.0f
#define ROOMTEMPERATURE_LOWERLIMIT 25.0f
#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT

//ProductLifeCycle
#define ROOMPRODUCTLIFECYCLE_UPPERLIMIT 10000.0
#define ROOMPRODUCTLIFECYCLE_LOWERLIMIT 1.0
#define STARTING_ROOMPRODUCTLIFECYCLE  ROOMPRODUCTLIFECYCLE_LOWERLIMIT

//SmokeErrState
#define ROOMSMOKEERRSTATE_UPPERLIMIT 0
#define ROOMSMOKEERRSTATE_LOWERLIMIT 0
#define STARTING_ROOMSMOKEERRSTATE  ROOMSMOKEERRSTATE_LOWERLIMIT

//SmokeAlertFlag  value =[0,2,4,8]
#define ROOMSMOKEALERTFLAG_UPPERLIMIT 8
#define ROOMSMOKEALERTFLAG_LOWERLIMIT 0
#define STARTING_ROOMSMOKEALERTFLAG  ROOMSMOKEALERTFLAG_LOWERLIMIT

//CODensity
#define ROOMCODENSITY_UPPERLIMIT 100
#define ROOMCODENSITY_LOWERLIMIT 0
#define STARTING_ROOMCODENSITY  ROOMCODENSITY_LOWERLIMIT

//BatteryCapacity
#define ROOMBATTERYCAPATCITY_UPPERLIMIT 100.0
#define ROOMBATTERYCAPATCITY_LOWERLIMIT 1.0
#define STARTING_ROOMBATTERYCAPATCITY  ROOMBATTERYCAPATCITY_LOWERLIMIT

//SmokeMuteFlag
#define ROOMSMOKEMUTEFLAG_UPPERLIMIT 0
#define ROOMSMOKEMUTEFLAG_LOWERLIMIT 0
#define STARTING_ROOMSMOKEMUTEFLAG  ROOMSMOKEMUTEFLAG_LOWERLIMIT

#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 2000
// # define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200

static char certDirectory[PATH_MAX + 1] = "../../../certs";
#define HOST_ADDRESS_SIZE 255
static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST;
static uint32_t port = AWS_IOT_MQTT_PORT;
static uint8_t numPubs = 5;

static void simulateRoomTemperature(float *pRoomTemperature) {
	static float deltaChange;

	if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) {
		deltaChange = -0.5f;
	} else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) {
		deltaChange = 0.5f;
	}

	*pRoomTemperature += deltaChange;
}

// ProductLifeCycle
static void simulateRoomProductLifeCycle(float *pRoomProductLifeCycle) {
	static float deltaChange;
	
	if(*pRoomProductLifeCycle >= ROOMPRODUCTLIFECYCLE_UPPERLIMIT) {
		deltaChange = -10;
	} else if(*pRoomProductLifeCycle <= ROOMPRODUCTLIFECYCLE_LOWERLIMIT) {
		deltaChange = 10;
	}

	*pRoomProductLifeCycle += deltaChange;
}

// SmokeErrState

static void simulateRoomSmokeErrState(int *pRoomSmokeErrState) {
	static int deltaChange;
	
	if(*pRoomSmokeErrState >= ROOMSMOKEERRSTATE_UPPERLIMIT) {
		deltaChange = -0;
	} else if(*pRoomSmokeErrState <= ROOMSMOKEERRSTATE_LOWERLIMIT) {
		deltaChange = 0;
	}

	*pRoomSmokeErrState += deltaChange;
}



// SmokeAlertFlag

static void simulateRoomSmokeAlertFlag(int *pRoomSmokeAlertFlag) {
	static int deltaChange;
	
	if(*pRoomSmokeAlertFlag >= ROOMSMOKEALERTFLAG_UPPERLIMIT) {
		deltaChange = -2;
	} else if(*pRoomSmokeAlertFlag <= ROOMSMOKEALERTFLAG_LOWERLIMIT) {
		deltaChange = 2;
	}

	*pRoomSmokeAlertFlag += deltaChange;
}


// CODensity
static void simulateRoomCODensity(float *pRoomCODensity) {
	static float deltaChange;
	
	if(*pRoomCODensity >= ROOMCODENSITY_UPPERLIMIT) {
		deltaChange = -5.0;
	} else if(*pRoomCODensity <= ROOMCODENSITY_LOWERLIMIT) {
		deltaChange = 5.0;
	}

	*pRoomCODensity += deltaChange;
}

// BatteryCapacity
static void simulateRoomBatteryCapacity(float *pRoomBatteryCapacity) {
	static float deltaChange;
	
	if(*pRoomBatteryCapacity >= ROOMBATTERYCAPATCITY_UPPERLIMIT) {
		deltaChange = -5.0;
	} else if(*pRoomBatteryCapacity <= ROOMBATTERYCAPATCITY_LOWERLIMIT) {
		deltaChange = 5.0;
	}

	*pRoomBatteryCapacity += deltaChange;
}

// SmokeMuteFlag
static void simulateRoomSmokeMuteFlag(int *pRoomSmokeMuteFlag) {
	static int deltaChange;
	
	if(*pRoomSmokeMuteFlag >= ROOMSMOKEMUTEFLAG_UPPERLIMIT) {
		deltaChange = -0;
	} else if(*pRoomSmokeMuteFlag <= ROOMSMOKEMUTEFLAG_LOWERLIMIT) {
		deltaChange = 0;
	}

	*pRoomSmokeMuteFlag += deltaChange;
}

void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
								const char *pReceivedJsonDocument, void *pContextData) {
	IOT_UNUSED(pThingName);
	IOT_UNUSED(action);
	IOT_UNUSED(pReceivedJsonDocument);
	IOT_UNUSED(pContextData);

	if(SHADOW_ACK_TIMEOUT == status) {
		IOT_INFO("Update Timeout--");
	} else if(SHADOW_ACK_REJECTED == status) {
		IOT_INFO("Update RejectedXX");
	} else if(SHADOW_ACK_ACCEPTED == status) {
		IOT_INFO("Update Accepted !!");
	}
}

void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
	IOT_UNUSED(pJsonString);
	IOT_UNUSED(JsonStringDataLen);

	if(pContext != NULL) {
		IOT_INFO("Delta - Window state changed to %d", *(bool *) (pContext->pData));
	}
}



void parseInputArgsForConnectParams(int argc, char **argv) {
	int opt;

	while(-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) {
		switch(opt) {
			case 'h':
				strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE);
				IOT_DEBUG("Host %s", optarg);
				break;
			case 'p':
				port = atoi(optarg);
				IOT_DEBUG("arg %s", optarg);
				break;
			case 'c':
				strncpy(certDirectory, optarg, PATH_MAX + 1);
				IOT_DEBUG("cert root directory %s", optarg);
				break;
			case 'n':
				numPubs = atoi(optarg);
				IOT_DEBUG("num pubs %s", optarg);
				break;
			case '?':
				if(optopt == 'c') {
					IOT_ERROR("Option -%c requires an argument.", optopt);
				} else if(isprint(optopt)) {
					IOT_WARN("Unknown option `-%c'.", optopt);
				} else {
					IOT_WARN("Unknown option character `\\x%x'.", optopt);
				}
				break;
			default:
				IOT_ERROR("ERROR in command line argument parsing");
				break;
		}
	}

}

int main(int argc, char **argv) {
	IoT_Error_t rc = FAILURE;

	char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
	size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
	float temperature = 0.0;
	float ProductLifeCycle = 1.0;
	int SmokeErrState = 0;
	//int SmokeAlertFlag = 0;
	//float CODensity = 0;
	float BatteryCapacity = 1.0;
	int SmokeMuteFlag = 0;
	
	int SmokeAlertFlag;
	printf("please input SmokeAlertFlag value[0,1,2,4,8]:");
	scanf("%d", &SmokeAlertFlag);
	
	float CODensity;
	printf("please input CODensity value(0--100):");
	scanf("%f", &CODensity);
	
	bool windowOpen = false;
	jsonStruct_t windowActuator;
	windowActuator.cb = windowActuate_Callback;
	windowActuator.pData = &windowOpen;
	windowActuator.dataLength = sizeof(bool);
	windowActuator.pKey = "windowOpen";
	windowActuator.type = SHADOW_JSON_BOOL;

	jsonStruct_t temperatureHandler;
	temperatureHandler.cb = NULL;
	temperatureHandler.pKey = "temperature";
	temperatureHandler.pData = &temperature;
	temperatureHandler.dataLength = sizeof(float);
	temperatureHandler.type = SHADOW_JSON_FLOAT;
	
	jsonStruct_t ProductLifeCycleHandler;
	ProductLifeCycleHandler.cb = NULL;
	ProductLifeCycleHandler.pKey = "ProductLifeCycle";
	ProductLifeCycleHandler.pData = &ProductLifeCycle;
	ProductLifeCycleHandler.dataLength = sizeof(float);
	ProductLifeCycleHandler.type = SHADOW_JSON_FLOAT;
	
	jsonStruct_t SmokeErrStateHandler;
	SmokeErrStateHandler.cb = NULL;
	SmokeErrStateHandler.pKey = "SmokeErrState";
	SmokeErrStateHandler.pData = &SmokeErrState;
	SmokeErrStateHandler.dataLength = sizeof(int);
	SmokeErrStateHandler.type = SHADOW_JSON_INT32;
	
	jsonStruct_t SmokeAlertFlagHandler;
	SmokeAlertFlagHandler.cb = NULL;
	SmokeAlertFlagHandler.pKey = "SmokeAlertFlag";
	SmokeAlertFlagHandler.pData = &SmokeAlertFlag;
	SmokeAlertFlagHandler.dataLength = sizeof(int);
	SmokeAlertFlagHandler.type = SHADOW_JSON_INT32;
	
	jsonStruct_t CODensityHandler;
	CODensityHandler.cb = NULL;
	CODensityHandler.pKey = "CODensity";
	CODensityHandler.pData = &CODensity;
	CODensityHandler.dataLength = sizeof(float);
	CODensityHandler.type = SHADOW_JSON_FLOAT;
	
	jsonStruct_t BatteryCapacityHandler;
	BatteryCapacityHandler.cb = NULL;
	BatteryCapacityHandler.pKey = "BatteryCapacity";
	BatteryCapacityHandler.pData = &BatteryCapacity;
	BatteryCapacityHandler.dataLength = sizeof(float);
	BatteryCapacityHandler.type = SHADOW_JSON_FLOAT;
	
	jsonStruct_t SmokeMuteFlagHandler;
	SmokeMuteFlagHandler.cb = NULL;
	SmokeMuteFlagHandler.pKey = "SmokeMuteFlag";
	SmokeMuteFlagHandler.pData = &SmokeMuteFlag;
	SmokeMuteFlagHandler.dataLength = sizeof(int);
	SmokeMuteFlagHandler.type = SHADOW_JSON_INT32;

	char rootCA[PATH_MAX + 1];
	char clientCRT[PATH_MAX + 1];
	char clientKey[PATH_MAX + 1];
	char CurrentWD[PATH_MAX + 1];

	IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);

	getcwd(CurrentWD, sizeof(CurrentWD));
	snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
	snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
	snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);

	IOT_DEBUG("rootCA %s", rootCA);
	IOT_DEBUG("clientCRT %s", clientCRT);
	IOT_DEBUG("clientKey %s", clientKey);

	parseInputArgsForConnectParams(argc, argv);

	// initialize the mqtt client
	AWS_IoT_Client mqttClient;

	ShadowInitParameters_t sp = ShadowInitParametersDefault;
	sp.pHost = AWS_IOT_MQTT_HOST;
	sp.port = AWS_IOT_MQTT_PORT;
	sp.pClientCRT = clientCRT;
	sp.pClientKey = clientKey;
	sp.pRootCA = rootCA;
	sp.enableAutoReconnect = false;
	sp.disconnectHandler = NULL;

	IOT_INFO("Shadow Init");
	rc = aws_iot_shadow_init(&mqttClient, &sp);
	if(SUCCESS != rc) {
		IOT_ERROR("Shadow Connection Error");
		return rc;
	}

	ShadowConnectParameters_t scp = ShadowConnectParametersDefault;
	scp.pMyThingName = AWS_IOT_MY_THING_NAME;
	scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
	scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);

	IOT_INFO("Shadow Connect");
	rc = aws_iot_shadow_connect(&mqttClient, &scp);
	if(SUCCESS != rc) {
		IOT_ERROR("Shadow Connection Error");
		return rc;
	}

	/*
	 * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
	 *  #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
	 *  #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
	 */
	rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true);
	if(SUCCESS != rc) {
		IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
		return rc;
	}

	rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator);

	if(SUCCESS != rc) {
		IOT_ERROR("Shadow Register Delta Error");
	}
	temperature = STARTING_ROOMTEMPERATURE;
	ProductLifeCycle = STARTING_ROOMPRODUCTLIFECYCLE;
	SmokeErrState = STARTING_ROOMSMOKEERRSTATE;
	// SmokeAlertFlag = STARTING_ROOMSMOKEALERTFLAG;   设置默认报警值
	// CODensity = STARTING_ROOMCODENSITY;  设置默认CODensity报警值
	BatteryCapacity = STARTING_ROOMBATTERYCAPATCITY;
	SmokeMuteFlag = STARTING_ROOMSMOKEMUTEFLAG;
	
	// loop and publish a change in temperature
	// NETWORK_ATTEMPTING_RECONNECT = 4   NETWORK_RECONNECTED = 3
	//while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) {
	if(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) {
		rc = aws_iot_shadow_yield(&mqttClient, 200);
		if(NETWORK_ATTEMPTING_RECONNECT == rc) {
			sleep(1);
			// If the client is attempting to reconnect we will skip the rest of the loop.
			//continue;
		}
		IOT_INFO("\n=======================================================================================\n");
	//	IOT_INFO("On Device: window state %s, BatteryCapacity state %.2f", windowOpen ? "true" : "false", BatteryCapacity);
		printf("BatteryCapacity state %.2f \n", BatteryCapacity );
		simulateRoomTemperature(&temperature);
		simulateRoomProductLifeCycle(&ProductLifeCycle);
		simulateRoomSmokeErrState(&SmokeErrState);
		//simulateRoomSmokeAlertFlag(&SmokeAlertFlag);
		//simulateRoomCODensity(&CODensity);
		simulateRoomBatteryCapacity(&BatteryCapacity);
		simulateRoomSmokeMuteFlag(&SmokeMuteFlag);

	// loop and publish a change in BatteryCapacity

		rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
		if(SUCCESS == rc) {
			/***
			rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, 
			&windowActuator);
			***/
			rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 6, &ProductLifeCycleHandler, &SmokeErrStateHandler, &SmokeAlertFlagHandler, &CODensityHandler, &BatteryCapacityHandler, &SmokeMuteFlagHandler);
			//&windowActuator,
			if(SUCCESS == rc) {
				rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
				if(SUCCESS == rc) {
					IOT_INFO("Update Shadow: %s", JsonDocumentBuffer);
					rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer,
											   ShadowUpdateStatusCallback, NULL, 4, true);
				}
			}
		}
		IOT_INFO("*****************************************************************************************\n");
		sleep(1);
	}

	if(SUCCESS != rc) {
		IOT_ERROR("An error occurred in the loop %d", rc);
	}

	IOT_INFO("Disconnecting");
	rc = aws_iot_shadow_disconnect(&mqttClient);

	if(SUCCESS != rc) {
		IOT_ERROR("Disconnect error %d", rc);
	}

	return rc;
}

=================================================================

以上是设备接入AWS IOT的方法,下面说下如何通过IOT core 将设备端的报警事件推送到APP端(app信息,和短信,电话)

注: https://www.thorntech.com/2016/09/aws-iot-to-send-text-message-notifications/  (在AWS IOT core 上配置rule topic, 订阅,发送SNS SMS 给客户端 APP )   -----已经试验过

先上示意图:

设备(烟感器)在AWS IOT core 平台上对应的就是 Things ,然后依次创建 证书(device),策略,将策略附加到证书上,然后下载证书(device),将证书导入到设备中。 下面提供的是一个rule , iot core 根据 rule engine 做后续操作,比如执行Lambda 函数里面的逻辑。

==================================================================

Lambda 将 alert event  发给SNS ,由SNS 推送消息(app, 短信,电话)给用户端。



const http = require('http');
const https = require('https');


console.log('Loading function');
    // Load the AWS SDK
    var AWS = require("aws-sdk");
    
    // Set up the code to call when the Lambda function is invoked
    exports.handler = (event, context, callback) => {
        // Load the message passed into the Lambda function into a JSON object 
     var eventText = JSON.stringify(event, null, 2);
       // Log a message to the console, you can view this text in the Monitoring tab in the Lambda console or in the CloudWatch Logs console
      console.log("Received event:", eventText);

      var message_1_SES = "The smoke alarm! Please note that there may be a fire in your home!"  ;
      var message_1_SMS = "【The smoke alarm】"+ "\n" + " Please note that there may be a fire in your home! Please check your home immediately!"  + "\n"+"\n"+" SmokeAlarm://open"  ;

      var message_1_APP = "SmokeAlarm!";
      var jsonMessage_1_APP ={
             "default": "This is the content of the push notification",
            "APNS_SANDBOX": "{\"aps\":{\"alert\": {\"title\": \"SmokeAlarm\",\"body\": \"The SmokeAlarm! Please note that there may be a fire in your home!\"},\"sound\":\"default\"}}"
            };
      
      var message_2_SES = " The BatteryCapacity is Low ! " ;
      var message_2_SMS = " The BatteryCapacity is Low !";
      var jsonMessage_2_APP = {
             "default": "This is the content of the push notification",
            "APNS_SANDBOX": "{\"aps\":{\"alert\": {\"title\": \"BatteryCapacity\",\"body\": \" The BatteryCapacity is Low !\"},\"sound\":\"default\"}}"
            }; 
      
      var message_4_SES = " End of product life cycle! " ;
      var message_4_SMS = " End of product life cycle! " ;
      var jsonMessage_4_APP = {
             "default": "This is the content of the push notification",
            "APNS_SANDBOX": "{\"aps\":{\"alert\": {\"title\": \"ProductCycle\",\"body\": \"  End of product life cycle!!\"},\"sound\":\"default\"}}"
            }; 
    
      var message_8_SES = "The CODensity Alarm!  There is poisonous gas in your home, please open the window immediately and leave the indoor environment!" ;
      var message_8_SMS = "【The CODensity Alarm】" + "\n" + "The CODensity Alarm!  There is poisonous gas in your home, please open the window immediately and leave the indoor environment!" ;
      var jsonMessage_8_APP = {
             "default": "This is the content of the push notification",
            "APNS_SANDBOX": "{\"aps\":{\"alert\": {\"title\": \"CODensityAlarm\",\"body\": \"The CODensity Alarm!  There is poisonous gas in your home, please open the window immediately and leave the indoor environment!!\"},\"badge\":1,\"sound\":\"default\"}}"
            }; 
   
   var body = '<xml><ToUserName><![CDATA[gh_836f9xxx358d]]></ToUserName><FromUserName><![CDATA[oTb0x5hvi2TRnJNPxQOYZxxxQ]]></FromUserName><CreateTime>1539765278</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[Easy1234567890]]></Content><MsgId>6613241512949142455</MsgId></xml>';
 
  // var json = JSON.stringify(body); 
  // var access_token = '14_HTUJQ4zcPn3Zc6uUAO0Yqo4Rv6nDhcch8n5F5cMF9yWEcSx5dsuXb1qG1DZTlJauvGnfSy8RP1ojQkx4YoDRzzslJDNLaQMmP7QWG3WwBTbo12qOvL9K7c_IScNG4EnSR9APP4OQFU1ZSqrDVQYaABAPKS';
   var postRequest = {
            host: 'ec2-54-190-199-48.us-west-2.compute.amazonaws.com',
            path: '/wx',
            port: 80,
            method: 'POST',
    //        body:body,
    headers: {
        'Cookie': "cookie",
        'Content-Type': 'text/xml',
     //  'Content-Type': 'application/json;charset=UTF-8',
        'Content-Length': Buffer.byteLength(body)
    }
};

 var buffer = "";
 var postdata = "";

var req = http.request( postRequest, function( res )    {
    

   console.log( res.statusCode );
   var buffer = "";
 
   res.on ( "postdata", function( postdata ) { 
       buffer = buffer + postdata; 
   } );
   res.on( "end", function( postdata ) { 
       console.log( buffer ); } );
});

req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
});

req.write( body );
req.end();

    
    console.log("Message to send: " + message_1_SES);
        
        // Create an SNS object
        var sns = new AWS.SNS();
        
        // Populate the parameters for the publish operation
 
         var SmokeAlertFlag_1_SES = {
            Message: message_1_SES,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo"
         };
         
       
         
         var SmokeAlertFlag_1_SMS = {
            Message: message_1_SMS,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_SMS"
         
         };
           var SmokeAlertFlag_1_APP = {
            Message: JSON.stringify(jsonMessage_1_APP),
         //   Message: payload,
           MessageStructure: "json",
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_APP"
         };
         
         
         var SmokeAlertFlag_2_SES = {
            Message: message_2_SES,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo"
         };
         var SmokeAlertFlag_2_SMS = {
            Message: message_2_SMS,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_SMS"
         };
         var SmokeAlertFlag_2_APP = {
            Message: JSON.stringify(jsonMessage_2_APP),
            MessageStructure: "json",
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_APP"
         };
         
         
           var SmokeAlertFlag_4_SES = {
            Message: message_4_SES,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo"
         };
         var SmokeAlertFlag_4_SMS = {
            Message: message_4_SMS,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_SMS"
         };
         var SmokeAlertFlag_4_APP = {
            Message: JSON.stringify(jsonMessage_4_APP),
             MessageStructure: "json",
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_APP"
         };
         
         
           var SmokeAlertFlag_8_SES = {
            Message: message_8_SES,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo"
         };
         var SmokeAlertFlag_8_SMS = {
            Message: message_8_SMS,
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_SMS"
         };
         var SmokeAlertFlag_8_APP = {
            Message: JSON.stringify(jsonMessage_8_APP),
            MessageStructure: "json",
            TopicArn: "arn:aws:sns:us-west-2:714007299995:SmokeSensor_Demo_APP"
         };
         if(event.state.reported.SmokeAlertFlag == 1){
                 sns.publish(SmokeAlertFlag_1_SES, context.done);
                 sns.publish(SmokeAlertFlag_1_SMS, context.done);
                 sns.publish(SmokeAlertFlag_1_APP, context.done);
            //   http.postMessage (SmokeAlertFlag_1_SES,'http://ec2-54-190-199-48.us-west-2.compute.amazonaws.com/wx');
                 
        }else if(event.state.reported.SmokeAlertFlag == 2){
                 sns.publish(SmokeAlertFlag_2_SES, context.done);
                 sns.publish(SmokeAlertFlag_2_SMS, context.done);
                 sns.publish(SmokeAlertFlag_2_APP, context.done);
                 
        }else if(event.state.reported.SmokeAlertFlag == 4){
                 sns.publish(SmokeAlertFlag_4_SES, context.done);
                 sns.publish(SmokeAlertFlag_4_SMS, context.done);
                 sns.publish(SmokeAlertFlag_4_APP, context.done);
                 
        }else if(event.state.reported.SmokeAlertFlag == 8){
                 sns.publish(SmokeAlertFlag_8_SES, context.done);
                 sns.publish(SmokeAlertFlag_8_SMS, context.done);
                 sns.publish(SmokeAlertFlag_8_APP, context.done);
        }
    };     

 

==========================================================================

Lambda 中有 接入微信硬件平台的code, 用来发送Smoke Alert Event 给微信公众号,并由公众号转发给关注该微信公众号的终端微信用户。

其架构如下:

=========================================================================

ec2 server 上的关键code:

handle.py

# -*- coding: utf-8 -*-
#python 27
#filename: handle.py
import hashlib
import web
import reply
import receive
import urllib2
import urllib
import json
class Handle(object):
   def GET(self):
        try:
            data = web.input()
            if len(data) == 0:
                return "hello, this is handle view"
            signature = data.signature
            timestamp = data.timestamp
            nonce = data.nonce
            echostr = data.echostr
            token = "helxxxaws" #请按照公众平台官网\基本配置中信息填写
            list = [token, timestamp, nonce]
            list.sort()
            sha1 = hashlib.sha1()
            map(sha1.update, list)
            hashcode = sha1.hexdigest()
            print "handle/GET func: hashcode, signature: ", hashcode, signature
            if hashcode == signature:
                return echostr
            else:
                return ""
        except Exception, Argument:
            return Argument
class Handle(object):
   def POST(self):
        try:
            webData = web.data()
            print "Handle Post webdata is ", webData
            htmlurl='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential' #grant_type为固定值
            htmldata={
                    'appid':'wxc5ad96e7xxxxxxx2',
                    'secret':'246fa64a45f486xxxxxxxxxxd65ff453'
                    }
            htmldata=urllib.urlencode(htmldata)
            html=urllib.urlopen(htmlurl,htmldata) #<addinfourl at 34758208 whose fp = <socket._fileobject object at 0x0212F570>>
            html=html.read()
            access_token=json.loads(html)['access_token']
            print "access_token=",access_token
   #后台打日志
            recMsg = receive.parse_xml(webData)
            if  isinstance(recMsg, receive.Msg) and recMsg.MsgType == 'text':
                url=('https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s'%access_token)
 #               url=base_url + urllib.urlencode(access_token)
                body = {
                    "touser": "oTb0x5hvi2TRxxxxxjgOYZUgVQ",
                    "msgtype": "text",
                    "text": {
                               "content": "The smoke alarm! Please note that there may be a fire in your home!"
                            }
                    }
                jdata = json.dumps(body) 
                headers = {'Content-Type': 'application/json'}
 #               data=urllib.urlencode(body)
                request = urllib2.Request(url, jdata)
                print "request=",request
                response = urllib2.urlopen(request)
                print"response=", response.read()
                return response.read()
                toUser = recMsg.FromUserName
                fromUser = recMsg.ToUserName
                content = "test"
                replyMsg = reply.TextMsg(toUser, fromUser, content)
                print "reply.textmsg=",replyMsg
                return replyMsg.send()
            else:
                print "暂且不处理"
                return "success"
        except Exception, Argment:
            return Argment

========================================================================

微信端 接收到的信息:

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值