#include "includes.h" // 来自Win10的root CA——Sectigo(AddTrust) const char *ca_cert = { "-----BEGIN CERTIFICATE-----\n\ MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU\n\ MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs\n\ IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290\n\ MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux\n\ FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h\n\ bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v\n\ dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt\n\ H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9\n\ uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX\n\ mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX\n\ a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN\n\ E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0\n\ WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD\n\ VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0\n\ Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU\n\ cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx\n\ IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN\n\ AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH\n\ YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5\n\ 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC\n\ Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX\n\ c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a\n\ mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=\n\ -----END CERTIFICATE-----\n" }; #if 0 // 来自LindeTelemTest.pem, for telemetry.test.linde.com const char *client_cert = { "Bag Attributes\n\ localKeyID: 01 00 00 00 \n\ subject=/CN=LindeTelemTest\n\ issuer=/CN=RootLindeTelemTest\n\ -----BEGIN CERTIFICATE-----\n\ MIICBTCCAXKgAwIBAgIQsAePmD4yBrxNOjXTSoR8WDAJBgUrDgMCHQUAMB0xGzAZ\n\ BgNVBAMTElJvb3RMaW5kZVRlbGVtVGVzdDAeFw0xOTA0MDkxNDIwNTNaFw0zOTEy\n\ MzEyMzU5NTlaMBkxFzAVBgNVBAMTDkxpbmRlVGVsZW1UZXN0MIGfMA0GCSqGSIb3\n\ DQEBAQUAA4GNADCBiQKBgQDWXFoXZu9g6qmooWJD1FNu7gdWOmNwokbZVA0c5xIN\n\ +sV++jTpD1HP87LWWodoeikNHRSLm5D8+4k08+JC3JFVslJn0jMFmWk752pC0pcP\n\ L65Ityt9JLELF4EzeIcp3n6evVlbsmAGxwvzQdq/0Tzk5XRsFBxGKyEw1WeV0zOb\n\ aQIDAQABo1IwUDBOBgNVHQEERzBFgBCyJA+/vhUnVMhI87j0nOxvoR8wHTEbMBkG\n\ A1UEAxMSUm9vdExpbmRlVGVsZW1UZXN0ghAel9uqpF3bqkGSfrB2pm0gMAkGBSsO\n\ AwIdBQADgYEAO4lrYCGNlDqUCWCBaGVdh8RPav7gD3bcr+10DzJxaS7SaHE1N+dA\n\ qbByd6I9uZhbPt9UEwWlMbPrRuFowhFjfD2/t0gSgjQUJmSRUZaEhZEWQK9OYyy5\n\ EaKTEUZqZF/69zNjjRxMmSaezdlJYgON2K+y7pqwwWTrotwFoil8snE=\n\ -----END CERTIFICATE-----\n" }; // 来自LindeTelemTest.pem, for telemetry.test.linde.com const char *client_key = { "Bag Attributes\n\ localKeyID: 01 00 00 00 \n\ Microsoft CSP Name: Microsoft Strong Cryptographic Provider\n\ friendlyName: PvkTmp:84aaec03-0e6d-4c65-a47d-b8f891f9f38d\n\ Key Attributes\n\ X509v3 Key Usage: 10 \n\ -----BEGIN PRIVATE KEY-----\n\ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANZcWhdm72Dqqaih\n\ YkPUU27uB1Y6Y3CiRtlUDRznEg36xX76NOkPUc/zstZah2h6KQ0dFIubkPz7iTTz\n\ 4kLckVWyUmfSMwWZaTvnakLSlw8vrki3K30ksQsXgTN4hynefp69WVuyYAbHC/NB\n\ 2r/RPOTldGwUHEYrITDVZ5XTM5tpAgMBAAECgYAZRGeGLKb4yJBZBTTdA/EVuU76\n\ FgXUp/wr7+Ffz8jsBuwyrHGCK0EcfwBMjf06DnQ6THw4fIzZlRi2Oi0obnFe7lzh\n\ bFfA72qRh844diATnVXEgwOL9bMOZYawkAYbgWq14YP5y2HBYn8CS/ii8OeXBxh4\n\ OnWWTKTD1+ZnPKvF9QJBAOwOSzo33vNHQTu53+7gcPT/TVqbFxRJbxAd37tnne93\n\ /QqvVV7ZwW2kvct0YGmN8J1A3qVHsPcO3yKYoJntF2MCQQDoeM9fPa9onBlHYpES\n\ 87PBjBdnkHdBUU28IEidDjKBwknwG+FuN2hNfj9WsBw2yRpvhWU8y+AOn0bn/RVE\n\ T3nDAkEA4J6xYtKral+RaV30AoC7u8X8O418pqdB8dobfV6Z4LcSqEozODCJaOXs\n\ XF9/JrIUFe8WbbwMXutd1LPbjt0W9QJBANRYXdt6RfpA89o/z5JHJv/5DfvcewIf\n\ 2OipeIp1SG88YDtBzFXXqJ94XTS64tqsMUiCyamR9JSGqscHZuCh0+8CQFzGDwWg\n\ NZOyyV/ttOXI6m8WvLif/givfoZGNfZfr39Z2+yLJeEnm1JRK2iWRuPwwfCCxWIR\n\ 47aQkh8VKyiXMho=\n\ -----END PRIVATE KEY-----\n" }; #else // 来自PraxairChina.pem, for telemetry.linde.com const char *client_cert = { "Bag Attributes\n\ localKeyID: 01 00 00 00 \n\ subject=/CN=PraxairChina\n\ issuer=/CN=RootLindeTelem\n\ -----BEGIN CERTIFICATE-----\n\ MIIB+zCCAWigAwIBAgIQHsNacaBKNbhGZR1hlXODrjAJBgUrDgMCHQUAMBkxFzAV\n\ BgNVBAMTDlJvb3RMaW5kZVRlbGVtMB4XDTE5MDUwNzAxMDgwOVoXDTM5MTIzMTIz\n\ NTk1OVowFzEVMBMGA1UEAxMMUHJheGFpckNoaW5hMIGfMA0GCSqGSIb3DQEBAQUA\n\ A4GNADCBiQKBgQCzjM8Enk1275ad4wdkQT7nDJrNQv4rzmivmapgSC7E74xHM2Bv\n\ tAVugDSsFNXqvYq2QHJ9XQbyoIoI81wHYwwrPMaSbli39tz1l+8TZK397BOutsLP\n\ ojxupuXDs7u4+b3Z5CnC6DegUeJm6qvQiBk+Zh2Rj8aYIrAQ3tyGfXL4NQIDAQAB\n\ o04wTDBKBgNVHQEEQzBBgBAQAXdJmRT6+eHp+YlqYGJFoRswGTEXMBUGA1UEAxMO\n\ Um9vdExpbmRlVGVsZW2CEGrbELsyedK8Rwv6ntamEAgwCQYFKw4DAh0FAAOBgQAs\n\ IiiFy/XNUEhV7+oK3Gs4YTP1KDzBtcilSHmdgK4QKfmeJOmlahRj2x5628LZq4nV\n\ tVF2/SCDzvhq6NqNCndTLgLUP0b7oEhe434uNEqmlJBjPeN3Cf4Niui7UkaLhTQ+\n\ Wo5uxCHHwXQGL4PdFrmsbQTX+yu4iUQHsVc1doNKEQ==\n\ -----END CERTIFICATE-----\n" }; // 来自PraxairChina.pem, for telemetry.linde.com const char *client_key = { "Bag Attributes\n\ localKeyID: 01 00 00 00 \n\ Microsoft CSP Name: Microsoft Strong Cryptographic Provider\n\ friendlyName: PvkTmp:ec094439-3ddc-47a6-93e0-90485b70a87c\n\ Key Attributes\n\ X509v3 Key Usage: 10 \n\ -----BEGIN PRIVATE KEY-----\n\ MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALOMzwSeTXbvlp3j\n\ B2RBPucMms1C/ivOaK+ZqmBILsTvjEczYG+0BW6ANKwU1eq9irZAcn1dBvKgigjz\n\ XAdjDCs8xpJuWLf23PWX7xNkrf3sE662ws+iPG6m5cOzu7j5vdnkKcLoN6BR4mbq\n\ q9CIGT5mHZGPxpgisBDe3IZ9cvg1AgMBAAECgYBXDOe5l357MYHWnqGQy8lRf9z1\n\ s4tDddlveZMPBzAVrwZV5uTUg3U2s9XVsGxeWPMNlYVsnlOmAoup90MhGbZl19dN\n\ C6ZnNkNiBXIXMtLk6KHoWg1wskPowk1GL3bssSDsaVqKhbnd8xkeXEemKH1Yk+D/\n\ 0azuDWS3AAt1ivQoKQJBAOOtZUbyunheA76BR/ac3RJYpVK9DX7Fij15z6s128H/\n\ g8pnJZdi+3EBeIe8y9Kl4p1qy9YUpbIwppqrtDTBffsCQQDJ4sC/qYQm3T2LmSr2\n\ GVD4WztwxSsO0VjM09XD/4GHn2rq3IKpTvNQCgaYIBC2Y6OTxJSfBU5RV/MAgk/v\n\ onuPAkEA4bfNOWp5Pc4PLjYjbzYS4hZqSL3O/EjBhbMXFGk/5nP4Z5idJxnlqCJK\n\ KWAePkdhhKkVTreHkkIzWhIyhT7zMwJAP+OmpAD9dV8mjvsWAXPZj/8vPGzpR3Mw\n\ 6wFO8Qv27fihWVoXb4Uwsu+5ToM3RsEZjzXy4rBHLK7slAipS2jcOQJAPIrm3Rnw\n\ 07kj+9B9WBKaFMIEIZWWLCE35iXzMByBXzk5G4VlPtOkr9Do4Gba7BML/UYSl4OY\n\ KcCnGVc+oGzPbA==\n\ -----END PRIVATE KEY-----\n" }; #endif // HTTP头格式串 const char *http_header_fmt = { "POST %s HTTP/1.1\r\n\ Host:%s\r\n\ Content-Type:application/json\r\n\ Content-Length:%d\r\n\ Connection:Keep-Alive\r\n\ \r\n" }; #if 0 // 范例记录,来自邮件 const char *json_data = { "{\n\ \"assets\":[\n\ {\n\ \"customerReference\":\"PRAXAIR-GOLD-CN-TEST\",\n\ \"assetIntegrationId\":\"0\",\n\ \"channels\":[\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Level\",\n\ \"channelNumber\":\"1\",\n\ \"scaledUnitName\":\"mm WC\",\n\ \"readings\":[\n\ {\n\ \"scaledMeasurement\":300.45678,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Level\",\n\ \"channelNumber\":\"2\",\n\ \"displayUnitName\":\"%% Full\",\n\ \"readings\":[\n\ {\n\ \"displayMeasurement\":50.34,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Level\",\n\ \"channelNumber\":\"3\",\n\ \"displayUnitName\":\"l\",\n\ \"readings\":[\n\ {\n\ \"displayMeasurement\":3068,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Gps\",\n\ \"channelNumber\":\"4\",\n\ \"readings\":[\n\ {\n\ \"longitude\":102.045678,\n\ \"latitude\":30.456789,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Pressure\",\n\ \"channelNumber\":\"5\",\n\ \"readings\":[\n\ {\n\ \"scaledMeasurement\":1.36,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Temperature\",\n\ \"channelNumber\":\"6\",\n\ \"readings\":[\n\ {\n\ \"scaledMeasurement\":-162,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"BatteryVoltage\",\n\ \"channelNumber\":\"7\",\n\ \"readings\":[\n\ {\n\ \"scaledMeasurement\":3.61,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Diagnostic\",\n\ \"channelNumber\":\"8\",\n\ \"readings\":[\n\ {\n\ \"scaledMeasurement\":1,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ },\n\ {\n\ \"deviceId\":\"2019041580001\",\n\ \"channelType\":\"Diagnostic\",\n\ \"channelNumber\":\"9\",\n\ \"readings\":[\n\ {\n\ \"scaledMeasurement\":2,\n\ \"timestamp\":\"2019-04-22T11:00:00Z\"\n\ }\n\ ]\n\ }\n\ ]\n\ }\n\ ]\n\ }\n" }; #endif #define JSON_BUFF_SIZE 2048 char JSON_buff[JSON_BUFF_SIZE]; char *JSON_data() { return JSON_buff; } void json_initialize() { memset(JSON_buff, 0, JSON_BUFF_SIZE); } void json_finish() { int offset = strlen(JSON_buff); // 去掉最后一行多余的',' if(offset > 0 && JSON_buff[offset - 1] == ',') JSON_buff[--offset] = 0; } void json_new_object() { int offset = strlen(JSON_buff); sprintf(JSON_buff + offset, "{"); } void json_end_object() { int offset = strlen(JSON_buff); // 去掉最后一行多余的',' if(offset > 0 && JSON_buff[offset - 1] == ',') offset--; sprintf(JSON_buff + offset, "},"); } void json_new_array(char *key) { int offset = strlen(JSON_buff); sprintf(JSON_buff + offset, "\"%s\":[", key); } void json_end_array() { int offset = strlen(JSON_buff); // 去掉最后一行多余的',' if(offset > 0 && JSON_buff[offset - 1] == ',') offset--; sprintf(JSON_buff + offset, "],"); } void json_new_intValue(char *key, int val) { int offset = strlen(JSON_buff); sprintf(JSON_buff + offset, "\"%s\":%d,", key, val); } void json_new_doubleValue(char *key, double val) { int offset = strlen(JSON_buff); sprintf(JSON_buff + offset, "\"%s\":%f,", key, val); } void json_new_stringValue(char *key, char *val) { int offset = strlen(JSON_buff); sprintf(JSON_buff + offset, "\"%s\":\"%s\",", key, val); } void json_new_boolValue(char *key, uint32_t val) { int offset = strlen(JSON_buff); sprintf(JSON_buff + offset, "\"%s\":%s,", key, val ? "true" : "false"); } // 以内为JSON解析函数,只解析最简单的记录(无数组和嵌套,数据类型只支持字符型、整型和浮点型) JSON_field JSON_Record[JSON_FIELD_COUNT]; int JSON_Parse_Symbol(char **src, char symbol) { while(**src == ' ' || **src == '\t' || **src == '\r' || **src == '\n') (*src)++; if(**src == symbol) { (*src)++; return 1; } return 0; } int JSON_Parse_Name(char **src, JSON_field *fld) { int len = 0; memset(fld->name, 0, JSON_NAME_LENGTH); while(**src != 0 && **src != '"' && len < JSON_NAME_LENGTH) { if(**src != '\r' && **src != '\n') { if(**src == '\\') (*src)++; fld->name[len++] = **src; } (*src)++; } if(len == 0) return 0; return 1; } int JSON_Parse_Val(char **src, JSON_field *fld) { long len = 0; int signCount = 0, pointCount = 0, quotCount = 0; char c; memset(fld->val, 0, JSON_VAL_LENGTH + 2); while(**src == ' ' || **src == '\t' || **src == '\r' || **src == '\n') (*src)++; while(**src != 0 && len < JSON_VAL_LENGTH + 2) { if(**src == ',' || **src == '}') { if(quotCount != 1) break; } if(**src != '\r' && **src != '\n') { c = **src; if(**src == '\\') (*src)++; if((quotCount == 0 && **src != ' ') || quotCount == 1) fld->val[len++] = **src; if(c == '"') quotCount++; } (*src)++; } if(fld->val[0] == '"' && fld->val[len - 1] == '"') { fld->type = JSON_TYPE_STRING; len -= 2; memmove(fld->val, fld->val + 1, len); fld->val[len] = 0; return 1; } for(int i = 0; i < len; i++) { if(fld->val[i] == '+' || fld->val[i] == '-') { if(i > 0 || signCount > 0) return 0; signCount++; } else if(fld->val[i] == '.') { if(pointCount > 0) return 0; if(i > 0 && !isdigit(fld->val[i - 1])) return 0; pointCount++; } else if(!isdigit(fld->val[i])) return 0; } if(pointCount == 0) fld->type = JSON_TYPE_INTEGER; else fld->type = JSON_TYPE_FLOAT; len = atoi(fld->val); fld->f = atof(fld->val); fld->i = len; return 1; } int JSON_Parse_Field(char **src, JSON_field *fld) { if(!JSON_Parse_Symbol(src, '"')) return 0; if(!JSON_Parse_Name(src, fld)) return 0; if(!JSON_Parse_Symbol(src, '"')) return 0; if(!JSON_Parse_Symbol(src, ':')) return 0; if(!JSON_Parse_Val(src, fld)) return 0; return 1; } int JSON_Parse_Record(char **src) { int fld_count = 0; JSON_field fld; memset(JSON_Record, 0, sizeof(JSON_Record)); // Object Begin if(!JSON_Parse_Symbol(src, '{')) return 0; while(1) { // Object End if(**src == '}') break; // 字段之间的分隔符(,) if(fld_count > 0) { if(!JSON_Parse_Symbol(src, ',')) return 0; } if(!JSON_Parse_Field(src, &fld)) return 0; JSON_Record[fld_count++] = fld; } if(!JSON_Parse_Symbol(src, '}')) return 0; return 1; }