Last active
January 6, 2022 13:50
-
-
Save chaeplin/fc9a9bdc9cb337e9680a to your computer and use it in GitHub Desktop.
WPA2 -EAP-TLS.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
WPA2-ENT EAP-TLS | |
based on joostd's code : https://github.com/joostd/esp8266-eduroam | |
https://github.com/joostd/esp8266-eduroam/blob/master/gen_cert.sh | |
wifi_station_set_cert_key | |
Function: Set certificate and private key for connecting to WPA2-ENTERPRISE AP. | |
Note: | |
• Connecting to WPA2-ENTERPRISE AP needs more than 26 KB memory, please ensure enough space (system_get_free_heap_size). | |
• So far, WPA2-ENTERPRISE can only support unencrypted certificate and private key, and only in PEM format. | |
‣ Header of certificate: - - - - - BEGIN CERTIFICATE - - - - - | |
‣ Headerofprivatekey:-----BEGINRSAPRIVATEKEY----- | |
or - - - - - BEGIN PRIVATE KEY - - - - - | |
• Please call this API to set certificate and private key before connecting to WPA2-ENTERPRISE AP and the application | |
needs to hold the certificate and private key. Call wifi_station_clear_cert_key to release resources and clear | |
status after connected to the target AP, and then the application can release the certificate and private key. | |
• If the private key is encrypted, please use openssl pkey command to change it to unencrypted file to use, | |
or use openssl rsa related commands to change it (or change the start TAG). | |
Prototype: | |
bool wifi_station_set_cert_key ( | |
uint8 *client_cert, | |
int client_cert_len, | |
uint8 *private_key, | |
int private_key_len, | |
uint8 *private_key_passwd, | |
int private_key_passwd_len, | |
) | |
Parameter: | |
uint8 *client_cert : certificate, HEX array | |
int client_cert_len : length of certificate | |
uint8 *private_key : private key, HEX array | |
int private_key_len : length of private key | |
uint8 *private_key_passwd : password for private key, to be supported, can only be NULL now. | |
int private_key_passwd_len : length of password, to be supported, can only be 0 now. | |
Return: | |
0 : succeed non-0 : fail | |
Example: | |
For example, the private key is - - - - - BEGIN PRIVATE KEY - - - - - ... ... ... ... | |
Then then array should be uint8 key[]={0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, ... ... 0x00 }; | |
It is the ASCII of the characters, and the array needs to be ended by 0x00. | |
*/ | |
// http://security.stackexchange.com/questions/47932/why-is-a-ca-certificate-required-for-eap-tls-clients | |
// | |
// by chaeplin 2016/01/20 | |
// https://github.com/chaeplin/esp8266_and_arduino | |
/* | |
SERVER : Rpi2(freeradius:EAP-TLS, mosquitto:tls1.1) | |
AP : DIR-868L(DD-WRT) | |
FreeHeap : 16.7K(20K is used by mqtt/tls) | |
*/ | |
// add ' -lwpa2' to end of https://github.com/esp8266/Arduino/blob/master/platform.txt#L33 | |
#include <ESP8266WiFi.h> | |
#include <WiFiClientSecure.h> | |
#include <PubSubClient.h> | |
#include <ESP8266mDNS.h> | |
#include <WiFiUdp.h> | |
#include <ArduinoOTA.h> | |
extern "C" { | |
#include "user_interface.h" | |
} | |
#include "/usr/local/src/ap_setting.h" | |
#define DEBUG_PRINT 1 | |
#define MQTT_TEST_SERVER { 192, 168, 10, 144 } | |
#define MQTT_TEST_USER "test1" | |
#define MQTT_TEST_PASS "test123" | |
// test | |
// 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x42, --> can't connect | |
// | |
// todo : use flash to store crt and key | |
uint8 espclient1_crt[] = { | |
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, | |
0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, | |
0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x51, 0x6a, 0x43, 0x43, | |
0x41, 0x69, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, | |
0x42, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, | |
0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x41, 0x59, | |
0x4d, 0x52, 0x59, 0x77, 0x46, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, | |
0x44, 0x41, 0x31, 0x74, 0x63, 0x58, 0x52, 0x30, 0x0a, 0x63, 0x32, 0x56, | |
0x79, 0x64, 0x6d, 0x56, 0x79, 0x49, 0x45, 0x4e, 0x42, 0x4d, 0x42, 0x34, | |
0x58, 0x44, 0x54, 0x45, 0x32, 0x4d, 0x44, 0x45, 0x78, 0x4f, 0x54, 0x45, | |
0x35, 0x4d, 0x7a, 0x6b, 0x78, 0x4f, 0x46, 0x6f, 0x58, 0x44, 0x54, 0x49, | |
0x32, 0x4d, 0x44, 0x45, 0x78, 0x4e, 0x6a, 0x45, 0x35, 0x4d, 0x7a, 0x6b, | |
0x78, 0x4f, 0x46, 0x6f, 0x77, 0x46, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45, | |
0x47, 0x0a, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4b, 0x5a, 0x58, | |
0x4e, 0x77, 0x59, 0x32, 0x78, 0x70, 0x5a, 0x57, 0x35, 0x30, 0x4d, 0x54, | |
0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, | |
0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, | |
0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, | |
0x6f, 0x43, 0x67, 0x67, 0x45, 0x42, 0x0a, 0x41, 0x4f, 0x64, 0x39, 0x48, | |
0x63, 0x4d, 0x32, 0x53, 0x73, 0x36, 0x4c, 0x4b, 0x2b, 0x68, 0x41, 0x34, | |
0x4f, 0x4d, 0x43, 0x66, 0x47, 0x6d, 0x42, 0x68, 0x48, 0x57, 0x73, 0x71, | |
0x59, 0x73, 0x4b, 0x6e, 0x2f, 0x30, 0x45, 0x36, 0x79, 0x64, 0x43, 0x4c, | |
0x43, 0x78, 0x47, 0x57, 0x70, 0x72, 0x58, 0x76, 0x64, 0x78, 0x38, 0x4a, | |
0x42, 0x31, 0x53, 0x50, 0x35, 0x34, 0x67, 0x55, 0x30, 0x57, 0x47, 0x0a, | |
0x74, 0x4a, 0x39, 0x2f, 0x37, 0x57, 0x41, 0x75, 0x46, 0x77, 0x35, 0x66, | |
0x56, 0x51, 0x61, 0x7a, 0x2f, 0x47, 0x48, 0x48, 0x4a, 0x4e, 0x6a, 0x63, | |
0x2b, 0x44, 0x64, 0x44, 0x4c, 0x43, 0x63, 0x67, 0x4d, 0x46, 0x72, 0x72, | |
0x31, 0x33, 0x37, 0x69, 0x7a, 0x78, 0x66, 0x41, 0x7a, 0x44, 0x43, 0x46, | |
0x2b, 0x76, 0x34, 0x65, 0x53, 0x78, 0x4d, 0x42, 0x42, 0x4a, 0x42, 0x50, | |
0x70, 0x36, 0x6c, 0x5a, 0x0a, 0x33, 0x43, 0x48, 0x64, 0x47, 0x46, 0x58, | |
0x2f, 0x66, 0x30, 0x42, 0x6f, 0x6c, 0x34, 0x72, 0x32, 0x73, 0x78, 0x39, | |
0x75, 0x6d, 0x71, 0x31, 0x68, 0x70, 0x49, 0x47, 0x63, 0x49, 0x38, 0x50, | |
0x69, 0x4a, 0x52, 0x54, 0x46, 0x66, 0x69, 0x55, 0x76, 0x35, 0x6e, 0x62, | |
0x6f, 0x53, 0x70, 0x59, 0x77, 0x57, 0x4b, 0x45, 0x55, 0x64, 0x67, 0x65, | |
0x4e, 0x52, 0x56, 0x45, 0x30, 0x46, 0x64, 0x45, 0x61, 0x0a, 0x33, 0x4b, | |
0x41, 0x62, 0x32, 0x4e, 0x7a, 0x64, 0x32, 0x6f, 0x6f, 0x2b, 0x2b, 0x55, | |
0x34, 0x4f, 0x37, 0x4b, 0x53, 0x69, 0x53, 0x35, 0x57, 0x36, 0x62, 0x67, | |
0x50, 0x6e, 0x7a, 0x48, 0x4d, 0x64, 0x64, 0x64, 0x54, 0x4d, 0x38, 0x57, | |
0x64, 0x64, 0x39, 0x7a, 0x35, 0x51, 0x6d, 0x43, 0x2b, 0x39, 0x5a, 0x5a, | |
0x49, 0x38, 0x57, 0x65, 0x42, 0x35, 0x45, 0x33, 0x61, 0x44, 0x52, 0x59, | |
0x4c, 0x67, 0x0a, 0x2b, 0x39, 0x48, 0x33, 0x64, 0x53, 0x44, 0x34, 0x59, | |
0x48, 0x72, 0x49, 0x48, 0x79, 0x4c, 0x4b, 0x6f, 0x39, 0x71, 0x52, 0x68, | |
0x6d, 0x63, 0x2b, 0x70, 0x54, 0x4a, 0x6d, 0x33, 0x43, 0x56, 0x54, 0x70, | |
0x64, 0x66, 0x2f, 0x52, 0x48, 0x6b, 0x36, 0x67, 0x6b, 0x30, 0x69, 0x6c, | |
0x43, 0x53, 0x2b, 0x51, 0x77, 0x56, 0x51, 0x31, 0x58, 0x45, 0x69, 0x45, | |
0x68, 0x73, 0x7a, 0x30, 0x32, 0x44, 0x6f, 0x0a, 0x4a, 0x77, 0x65, 0x4a, | |
0x2b, 0x71, 0x54, 0x79, 0x75, 0x46, 0x71, 0x33, 0x55, 0x34, 0x45, 0x64, | |
0x33, 0x5a, 0x5a, 0x50, 0x76, 0x61, 0x63, 0x43, 0x41, 0x77, 0x45, 0x41, | |
0x41, 0x61, 0x4f, 0x42, 0x6d, 0x54, 0x43, 0x42, 0x6c, 0x6a, 0x41, 0x4a, | |
0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x4d, 0x45, 0x41, 0x6a, 0x41, 0x41, | |
0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, | |
0x0a, 0x42, 0x42, 0x52, 0x76, 0x39, 0x51, 0x75, 0x37, 0x32, 0x76, 0x50, | |
0x71, 0x42, 0x78, 0x41, 0x35, 0x5a, 0x42, 0x57, 0x2b, 0x78, 0x77, 0x34, | |
0x56, 0x50, 0x43, 0x57, 0x30, 0x49, 0x6a, 0x42, 0x49, 0x42, 0x67, 0x4e, | |
0x56, 0x48, 0x53, 0x4d, 0x45, 0x51, 0x54, 0x41, 0x2f, 0x67, 0x42, 0x53, | |
0x78, 0x6b, 0x54, 0x48, 0x31, 0x77, 0x4d, 0x70, 0x6f, 0x6d, 0x37, 0x56, | |
0x79, 0x65, 0x73, 0x64, 0x62, 0x0a, 0x7a, 0x70, 0x7a, 0x62, 0x54, 0x35, | |
0x58, 0x74, 0x55, 0x71, 0x45, 0x63, 0x70, 0x42, 0x6f, 0x77, 0x47, 0x44, | |
0x45, 0x57, 0x4d, 0x42, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, | |
0x77, 0x4e, 0x62, 0x58, 0x46, 0x30, 0x64, 0x48, 0x4e, 0x6c, 0x63, 0x6e, | |
0x5a, 0x6c, 0x63, 0x69, 0x42, 0x44, 0x51, 0x59, 0x49, 0x4a, 0x41, 0x4a, | |
0x64, 0x34, 0x4c, 0x2f, 0x76, 0x6f, 0x4a, 0x36, 0x4d, 0x55, 0x0a, 0x4d, | |
0x42, 0x4d, 0x47, 0x41, 0x31, 0x55, 0x64, 0x4a, 0x51, 0x51, 0x4d, 0x4d, | |
0x41, 0x6f, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, | |
0x77, 0x4d, 0x43, 0x4d, 0x41, 0x73, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, | |
0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x48, 0x67, 0x44, 0x41, 0x4e, 0x42, | |
0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, | |
0x51, 0x73, 0x46, 0x0a, 0x41, 0x41, 0x4f, 0x43, 0x41, 0x51, 0x45, 0x41, | |
0x44, 0x50, 0x47, 0x4e, 0x31, 0x62, 0x4c, 0x57, 0x45, 0x49, 0x35, 0x4a, | |
0x35, 0x6d, 0x4d, 0x31, 0x61, 0x54, 0x4c, 0x64, 0x38, 0x63, 0x50, 0x76, | |
0x49, 0x62, 0x4e, 0x4f, 0x72, 0x6c, 0x63, 0x4c, 0x36, 0x70, 0x64, 0x62, | |
0x48, 0x63, 0x2b, 0x52, 0x69, 0x71, 0x42, 0x71, 0x33, 0x61, 0x64, 0x61, | |
0x74, 0x56, 0x5a, 0x71, 0x2f, 0x38, 0x76, 0x62, 0x0a, 0x73, 0x50, 0x43, | |
0x64, 0x71, 0x49, 0x7a, 0x30, 0x58, 0x47, 0x30, 0x37, 0x65, 0x50, 0x51, | |
0x77, 0x59, 0x51, 0x7a, 0x64, 0x63, 0x4f, 0x77, 0x67, 0x64, 0x7a, 0x78, | |
0x4a, 0x73, 0x76, 0x4e, 0x42, 0x47, 0x62, 0x77, 0x36, 0x47, 0x4a, 0x6d, | |
0x36, 0x32, 0x6c, 0x70, 0x52, 0x42, 0x2b, 0x62, 0x41, 0x30, 0x76, 0x79, | |
0x2b, 0x71, 0x67, 0x6e, 0x34, 0x32, 0x6c, 0x78, 0x32, 0x57, 0x56, 0x4b, | |
0x4d, 0x0a, 0x66, 0x53, 0x68, 0x68, 0x43, 0x59, 0x61, 0x71, 0x59, 0x52, | |
0x46, 0x5a, 0x72, 0x4a, 0x52, 0x66, 0x2b, 0x79, 0x58, 0x65, 0x61, 0x74, | |
0x58, 0x74, 0x64, 0x4a, 0x4d, 0x69, 0x75, 0x5a, 0x6f, 0x64, 0x55, 0x52, | |
0x36, 0x70, 0x32, 0x68, 0x35, 0x6b, 0x42, 0x52, 0x6c, 0x45, 0x34, 0x62, | |
0x72, 0x6d, 0x73, 0x66, 0x5a, 0x71, 0x33, 0x44, 0x4e, 0x53, 0x34, 0x33, | |
0x6e, 0x65, 0x2f, 0x72, 0x6f, 0x49, 0x0a, 0x31, 0x2f, 0x66, 0x76, 0x43, | |
0x31, 0x45, 0x51, 0x6f, 0x79, 0x5a, 0x71, 0x2b, 0x6f, 0x44, 0x32, 0x4e, | |
0x4a, 0x53, 0x2f, 0x38, 0x4f, 0x64, 0x58, 0x52, 0x58, 0x43, 0x36, 0x43, | |
0x32, 0x56, 0x69, 0x6d, 0x51, 0x62, 0x4e, 0x69, 0x67, 0x75, 0x42, 0x71, | |
0x73, 0x71, 0x35, 0x32, 0x36, 0x4d, 0x71, 0x31, 0x7a, 0x37, 0x57, 0x31, | |
0x6f, 0x50, 0x7a, 0x66, 0x5a, 0x75, 0x61, 0x30, 0x61, 0x4c, 0x6e, 0x0a, | |
0x64, 0x6f, 0x53, 0x63, 0x67, 0x44, 0x52, 0x4a, 0x69, 0x65, 0x37, 0x65, | |
0x69, 0x77, 0x52, 0x33, 0x74, 0x46, 0x66, 0x49, 0x66, 0x74, 0x32, 0x4a, | |
0x4a, 0x44, 0x55, 0x6e, 0x6d, 0x55, 0x6c, 0x57, 0x39, 0x46, 0x2b, 0x54, | |
0x74, 0x55, 0x48, 0x6d, 0x73, 0x76, 0x78, 0x4e, 0x50, 0x30, 0x58, 0x31, | |
0x57, 0x68, 0x53, 0x36, 0x36, 0x70, 0x66, 0x64, 0x43, 0x45, 0x61, 0x6a, | |
0x47, 0x59, 0x6c, 0x42, 0x0a, 0x6b, 0x33, 0x78, 0x57, 0x4b, 0x74, 0x6f, | |
0x32, 0x78, 0x4c, 0x45, 0x65, 0x69, 0x71, 0x71, 0x72, 0x31, 0x32, 0x64, | |
0x39, 0x64, 0x66, 0x34, 0x52, 0x52, 0x2b, 0x2b, 0x52, 0x6f, 0x77, 0x3d, | |
0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, | |
0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, | |
0x2d, 0x2d, 0x2d, 0x0a, 0x00 | |
}; | |
uint8 espclient1_key[] = { | |
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, | |
0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, | |
0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x45, 0x76, 0x67, 0x49, 0x42, | |
0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, | |
0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, | |
0x42, 0x4b, 0x67, 0x77, 0x67, 0x67, 0x53, 0x6b, 0x41, 0x67, 0x45, 0x41, | |
0x41, 0x6f, 0x49, 0x42, 0x41, 0x51, 0x44, 0x6e, 0x66, 0x52, 0x33, 0x44, | |
0x4e, 0x6b, 0x72, 0x4f, 0x69, 0x79, 0x76, 0x6f, 0x0a, 0x51, 0x4f, 0x44, | |
0x6a, 0x41, 0x6e, 0x78, 0x70, 0x67, 0x59, 0x52, 0x31, 0x72, 0x4b, 0x6d, | |
0x4c, 0x43, 0x70, 0x2f, 0x39, 0x42, 0x4f, 0x73, 0x6e, 0x51, 0x69, 0x77, | |
0x73, 0x52, 0x6c, 0x71, 0x61, 0x31, 0x37, 0x33, 0x63, 0x66, 0x43, 0x51, | |
0x64, 0x55, 0x6a, 0x2b, 0x65, 0x49, 0x46, 0x4e, 0x46, 0x68, 0x72, 0x53, | |
0x66, 0x66, 0x2b, 0x31, 0x67, 0x4c, 0x68, 0x63, 0x4f, 0x58, 0x31, 0x55, | |
0x47, 0x0a, 0x73, 0x2f, 0x78, 0x68, 0x78, 0x79, 0x54, 0x59, 0x33, 0x50, | |
0x67, 0x33, 0x51, 0x79, 0x77, 0x6e, 0x49, 0x44, 0x42, 0x61, 0x36, 0x39, | |
0x64, 0x2b, 0x34, 0x73, 0x38, 0x58, 0x77, 0x4d, 0x77, 0x77, 0x68, 0x66, | |
0x72, 0x2b, 0x48, 0x6b, 0x73, 0x54, 0x41, 0x51, 0x53, 0x51, 0x54, 0x36, | |
0x65, 0x70, 0x57, 0x64, 0x77, 0x68, 0x33, 0x52, 0x68, 0x56, 0x2f, 0x33, | |
0x39, 0x41, 0x61, 0x4a, 0x65, 0x4b, 0x0a, 0x39, 0x72, 0x4d, 0x66, 0x62, | |
0x70, 0x71, 0x74, 0x59, 0x61, 0x53, 0x42, 0x6e, 0x43, 0x50, 0x44, 0x34, | |
0x69, 0x55, 0x55, 0x78, 0x58, 0x34, 0x6c, 0x4c, 0x2b, 0x5a, 0x32, 0x36, | |
0x45, 0x71, 0x57, 0x4d, 0x46, 0x69, 0x68, 0x46, 0x48, 0x59, 0x48, 0x6a, | |
0x55, 0x56, 0x52, 0x4e, 0x42, 0x58, 0x52, 0x47, 0x74, 0x79, 0x67, 0x47, | |
0x39, 0x6a, 0x63, 0x33, 0x64, 0x71, 0x4b, 0x50, 0x76, 0x6c, 0x4f, 0x0a, | |
0x44, 0x75, 0x79, 0x6b, 0x6f, 0x6b, 0x75, 0x56, 0x75, 0x6d, 0x34, 0x44, | |
0x35, 0x38, 0x78, 0x7a, 0x48, 0x58, 0x58, 0x55, 0x7a, 0x50, 0x46, 0x6e, | |
0x58, 0x66, 0x63, 0x2b, 0x55, 0x4a, 0x67, 0x76, 0x76, 0x57, 0x57, 0x53, | |
0x50, 0x46, 0x6e, 0x67, 0x65, 0x52, 0x4e, 0x32, 0x67, 0x30, 0x57, 0x43, | |
0x34, 0x50, 0x76, 0x52, 0x39, 0x33, 0x55, 0x67, 0x2b, 0x47, 0x42, 0x36, | |
0x79, 0x42, 0x38, 0x69, 0x0a, 0x79, 0x71, 0x50, 0x61, 0x6b, 0x59, 0x5a, | |
0x6e, 0x50, 0x71, 0x55, 0x79, 0x5a, 0x74, 0x77, 0x6c, 0x55, 0x36, 0x58, | |
0x58, 0x2f, 0x30, 0x52, 0x35, 0x4f, 0x6f, 0x4a, 0x4e, 0x49, 0x70, 0x51, | |
0x6b, 0x76, 0x6b, 0x4d, 0x46, 0x55, 0x4e, 0x56, 0x78, 0x49, 0x68, 0x49, | |
0x62, 0x4d, 0x39, 0x4e, 0x67, 0x36, 0x43, 0x63, 0x48, 0x69, 0x66, 0x71, | |
0x6b, 0x38, 0x72, 0x68, 0x61, 0x74, 0x31, 0x4f, 0x42, 0x0a, 0x48, 0x64, | |
0x32, 0x57, 0x54, 0x37, 0x32, 0x6e, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, | |
0x45, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4b, 0x31, 0x70, 0x6e, 0x67, | |
0x30, 0x71, 0x4d, 0x39, 0x6f, 0x4d, 0x69, 0x65, 0x54, 0x67, 0x44, 0x56, | |
0x67, 0x68, 0x2b, 0x5a, 0x39, 0x30, 0x42, 0x67, 0x32, 0x39, 0x50, 0x66, | |
0x6c, 0x4b, 0x43, 0x56, 0x59, 0x62, 0x42, 0x43, 0x6f, 0x52, 0x75, 0x56, | |
0x4f, 0x6c, 0x0a, 0x6c, 0x4b, 0x52, 0x67, 0x72, 0x2f, 0x74, 0x6e, 0x43, | |
0x41, 0x72, 0x72, 0x48, 0x58, 0x74, 0x51, 0x6a, 0x66, 0x45, 0x4d, 0x6d, | |
0x32, 0x7a, 0x4e, 0x41, 0x62, 0x39, 0x47, 0x5a, 0x38, 0x45, 0x39, 0x69, | |
0x30, 0x32, 0x4e, 0x4d, 0x61, 0x6a, 0x78, 0x37, 0x56, 0x6d, 0x45, 0x46, | |
0x33, 0x49, 0x57, 0x6f, 0x52, 0x48, 0x69, 0x58, 0x44, 0x63, 0x51, 0x62, | |
0x41, 0x76, 0x43, 0x7a, 0x77, 0x37, 0x6c, 0x0a, 0x51, 0x46, 0x47, 0x74, | |
0x58, 0x4c, 0x78, 0x58, 0x5a, 0x7a, 0x67, 0x69, 0x55, 0x41, 0x2f, 0x6e, | |
0x6a, 0x42, 0x73, 0x69, 0x6c, 0x50, 0x54, 0x4e, 0x55, 0x7a, 0x6a, 0x42, | |
0x51, 0x4d, 0x75, 0x34, 0x54, 0x71, 0x59, 0x73, 0x62, 0x7a, 0x31, 0x42, | |
0x74, 0x78, 0x2f, 0x68, 0x67, 0x4d, 0x49, 0x54, 0x66, 0x50, 0x74, 0x32, | |
0x41, 0x76, 0x39, 0x50, 0x66, 0x31, 0x4e, 0x4f, 0x55, 0x65, 0x43, 0x4b, | |
0x0a, 0x63, 0x4a, 0x52, 0x36, 0x39, 0x47, 0x30, 0x65, 0x4c, 0x56, 0x47, | |
0x49, 0x6d, 0x42, 0x56, 0x68, 0x4a, 0x6d, 0x4a, 0x78, 0x4c, 0x4d, 0x34, | |
0x65, 0x35, 0x6c, 0x77, 0x73, 0x33, 0x52, 0x2b, 0x73, 0x59, 0x2f, 0x6f, | |
0x36, 0x55, 0x6f, 0x72, 0x34, 0x48, 0x30, 0x30, 0x47, 0x43, 0x36, 0x65, | |
0x66, 0x4e, 0x73, 0x5a, 0x49, 0x79, 0x4b, 0x59, 0x44, 0x42, 0x56, 0x5a, | |
0x75, 0x48, 0x45, 0x47, 0x76, 0x0a, 0x6b, 0x4d, 0x55, 0x34, 0x41, 0x57, | |
0x5a, 0x46, 0x48, 0x62, 0x43, 0x4f, 0x2f, 0x65, 0x48, 0x75, 0x38, 0x34, | |
0x70, 0x63, 0x6e, 0x6a, 0x33, 0x4b, 0x58, 0x5a, 0x75, 0x55, 0x31, 0x6e, | |
0x6c, 0x4a, 0x53, 0x6f, 0x71, 0x66, 0x66, 0x4f, 0x6e, 0x70, 0x32, 0x58, | |
0x74, 0x55, 0x59, 0x58, 0x74, 0x72, 0x2b, 0x2b, 0x63, 0x7a, 0x48, 0x2f, | |
0x59, 0x71, 0x59, 0x63, 0x2f, 0x4e, 0x68, 0x6f, 0x4f, 0x59, 0x0a, 0x44, | |
0x70, 0x58, 0x59, 0x46, 0x4f, 0x6a, 0x39, 0x7a, 0x7a, 0x59, 0x58, 0x41, | |
0x71, 0x45, 0x6e, 0x32, 0x65, 0x4a, 0x58, 0x46, 0x56, 0x65, 0x77, 0x72, | |
0x76, 0x63, 0x52, 0x37, 0x69, 0x52, 0x76, 0x66, 0x43, 0x4a, 0x4b, 0x64, | |
0x43, 0x31, 0x6b, 0x69, 0x50, 0x6b, 0x43, 0x67, 0x59, 0x45, 0x41, 0x2f, | |
0x70, 0x79, 0x55, 0x66, 0x66, 0x30, 0x32, 0x67, 0x64, 0x6a, 0x66, 0x45, | |
0x63, 0x55, 0x75, 0x0a, 0x74, 0x65, 0x51, 0x53, 0x63, 0x67, 0x31, 0x66, | |
0x6d, 0x79, 0x55, 0x30, 0x4c, 0x38, 0x2f, 0x76, 0x55, 0x51, 0x2f, 0x4c, | |
0x73, 0x39, 0x57, 0x77, 0x6a, 0x76, 0x4a, 0x4c, 0x50, 0x70, 0x31, 0x63, | |
0x44, 0x6e, 0x33, 0x43, 0x52, 0x64, 0x46, 0x31, 0x42, 0x7a, 0x6c, 0x2f, | |
0x34, 0x66, 0x65, 0x54, 0x48, 0x52, 0x73, 0x50, 0x64, 0x48, 0x45, 0x51, | |
0x50, 0x50, 0x70, 0x63, 0x63, 0x6d, 0x78, 0x59, 0x0a, 0x48, 0x44, 0x47, | |
0x37, 0x45, 0x59, 0x4e, 0x6e, 0x35, 0x38, 0x72, 0x6d, 0x70, 0x69, 0x79, | |
0x76, 0x6e, 0x2f, 0x30, 0x32, 0x2b, 0x68, 0x46, 0x63, 0x78, 0x4f, 0x76, | |
0x78, 0x55, 0x42, 0x36, 0x6d, 0x58, 0x78, 0x4b, 0x4c, 0x51, 0x62, 0x6e, | |
0x79, 0x45, 0x76, 0x4a, 0x32, 0x72, 0x64, 0x72, 0x69, 0x4a, 0x56, 0x66, | |
0x6d, 0x58, 0x61, 0x7a, 0x49, 0x75, 0x6a, 0x39, 0x4b, 0x4a, 0x48, 0x36, | |
0x72, 0x0a, 0x38, 0x59, 0x34, 0x2f, 0x48, 0x68, 0x4d, 0x44, 0x76, 0x6d, | |
0x61, 0x34, 0x54, 0x76, 0x4f, 0x47, 0x71, 0x53, 0x67, 0x50, 0x55, 0x4b, | |
0x56, 0x70, 0x32, 0x41, 0x73, 0x43, 0x67, 0x59, 0x45, 0x41, 0x36, 0x4d, | |
0x42, 0x43, 0x48, 0x58, 0x54, 0x77, 0x6a, 0x52, 0x38, 0x6a, 0x43, 0x57, | |
0x6a, 0x68, 0x54, 0x44, 0x4a, 0x69, 0x37, 0x52, 0x30, 0x59, 0x59, 0x47, | |
0x33, 0x65, 0x49, 0x4a, 0x48, 0x70, 0x0a, 0x70, 0x52, 0x63, 0x72, 0x4e, | |
0x31, 0x49, 0x64, 0x48, 0x39, 0x4e, 0x61, 0x53, 0x45, 0x70, 0x67, 0x34, | |
0x31, 0x2f, 0x4d, 0x74, 0x63, 0x34, 0x41, 0x68, 0x52, 0x6e, 0x73, 0x35, | |
0x68, 0x65, 0x72, 0x76, 0x6f, 0x70, 0x54, 0x31, 0x59, 0x33, 0x7a, 0x75, | |
0x44, 0x58, 0x38, 0x78, 0x46, 0x4e, 0x70, 0x49, 0x47, 0x6f, 0x57, 0x63, | |
0x4f, 0x69, 0x6b, 0x66, 0x46, 0x70, 0x75, 0x62, 0x63, 0x43, 0x4a, 0x0a, | |
0x63, 0x35, 0x4f, 0x57, 0x38, 0x32, 0x45, 0x76, 0x68, 0x68, 0x46, 0x73, | |
0x76, 0x2f, 0x30, 0x57, 0x65, 0x4e, 0x56, 0x48, 0x62, 0x5a, 0x33, 0x52, | |
0x56, 0x52, 0x35, 0x72, 0x45, 0x61, 0x78, 0x45, 0x35, 0x54, 0x67, 0x68, | |
0x68, 0x6a, 0x4c, 0x61, 0x6f, 0x4d, 0x47, 0x67, 0x2f, 0x46, 0x64, 0x5a, | |
0x58, 0x71, 0x44, 0x4b, 0x52, 0x65, 0x6d, 0x57, 0x39, 0x46, 0x55, 0x31, | |
0x58, 0x35, 0x2f, 0x4d, 0x0a, 0x6f, 0x6f, 0x38, 0x4c, 0x49, 0x4b, 0x4a, | |
0x49, 0x52, 0x6c, 0x55, 0x43, 0x67, 0x59, 0x45, 0x41, 0x33, 0x53, 0x39, | |
0x66, 0x58, 0x48, 0x66, 0x74, 0x73, 0x79, 0x32, 0x59, 0x30, 0x39, 0x49, | |
0x74, 0x65, 0x76, 0x77, 0x50, 0x2f, 0x68, 0x36, 0x61, 0x45, 0x4b, 0x68, | |
0x6f, 0x52, 0x71, 0x54, 0x6e, 0x37, 0x4d, 0x37, 0x42, 0x45, 0x70, 0x41, | |
0x76, 0x32, 0x6d, 0x36, 0x6f, 0x61, 0x56, 0x50, 0x41, 0x0a, 0x6c, 0x69, | |
0x49, 0x76, 0x39, 0x41, 0x45, 0x37, 0x48, 0x6a, 0x53, 0x59, 0x59, 0x4e, | |
0x42, 0x33, 0x62, 0x39, 0x43, 0x44, 0x51, 0x34, 0x2b, 0x35, 0x49, 0x4a, | |
0x41, 0x4b, 0x59, 0x61, 0x69, 0x33, 0x66, 0x6e, 0x37, 0x42, 0x57, 0x54, | |
0x79, 0x44, 0x74, 0x6e, 0x79, 0x77, 0x6c, 0x47, 0x6d, 0x37, 0x68, 0x45, | |
0x77, 0x77, 0x52, 0x31, 0x74, 0x76, 0x38, 0x4f, 0x35, 0x62, 0x61, 0x31, | |
0x50, 0x46, 0x0a, 0x43, 0x6c, 0x43, 0x4d, 0x77, 0x32, 0x4e, 0x71, 0x35, | |
0x59, 0x54, 0x58, 0x44, 0x72, 0x39, 0x59, 0x75, 0x45, 0x49, 0x39, 0x4d, | |
0x4f, 0x47, 0x61, 0x57, 0x78, 0x6f, 0x43, 0x4b, 0x65, 0x51, 0x56, 0x4d, | |
0x54, 0x70, 0x32, 0x6f, 0x49, 0x53, 0x36, 0x4f, 0x74, 0x7a, 0x33, 0x66, | |
0x6a, 0x62, 0x57, 0x6f, 0x2f, 0x72, 0x57, 0x47, 0x79, 0x51, 0x6e, 0x35, | |
0x2f, 0x4d, 0x43, 0x67, 0x59, 0x42, 0x2b, 0x0a, 0x33, 0x56, 0x79, 0x73, | |
0x52, 0x62, 0x4e, 0x67, 0x6d, 0x4a, 0x6f, 0x32, 0x5a, 0x4d, 0x35, 0x35, | |
0x41, 0x2f, 0x58, 0x63, 0x48, 0x4d, 0x48, 0x4f, 0x76, 0x64, 0x51, 0x58, | |
0x6d, 0x4c, 0x44, 0x72, 0x35, 0x61, 0x63, 0x4f, 0x72, 0x6c, 0x6c, 0x6c, | |
0x6f, 0x59, 0x52, 0x53, 0x5a, 0x77, 0x68, 0x4d, 0x70, 0x30, 0x6b, 0x6a, | |
0x78, 0x37, 0x65, 0x4d, 0x31, 0x55, 0x62, 0x46, 0x58, 0x42, 0x32, 0x6d, | |
0x0a, 0x37, 0x43, 0x73, 0x70, 0x2b, 0x67, 0x66, 0x67, 0x58, 0x72, 0x7a, | |
0x36, 0x48, 0x69, 0x54, 0x74, 0x49, 0x43, 0x59, 0x2f, 0x51, 0x4f, 0x39, | |
0x33, 0x51, 0x4b, 0x74, 0x30, 0x63, 0x7a, 0x2f, 0x34, 0x6d, 0x58, 0x66, | |
0x73, 0x44, 0x51, 0x73, 0x6b, 0x58, 0x70, 0x63, 0x53, 0x52, 0x74, 0x64, | |
0x61, 0x34, 0x5a, 0x58, 0x66, 0x62, 0x2b, 0x68, 0x4d, 0x4a, 0x78, 0x70, | |
0x68, 0x4e, 0x61, 0x38, 0x50, 0x0a, 0x36, 0x66, 0x71, 0x4c, 0x39, 0x57, | |
0x67, 0x70, 0x75, 0x36, 0x45, 0x4f, 0x4b, 0x6d, 0x5a, 0x79, 0x4a, 0x39, | |
0x35, 0x5a, 0x49, 0x53, 0x76, 0x41, 0x33, 0x6a, 0x6b, 0x4c, 0x65, 0x45, | |
0x54, 0x49, 0x54, 0x6f, 0x50, 0x59, 0x4d, 0x39, 0x79, 0x46, 0x53, 0x51, | |
0x4b, 0x42, 0x67, 0x45, 0x57, 0x48, 0x4c, 0x4b, 0x2f, 0x5a, 0x57, 0x5a, | |
0x37, 0x47, 0x6d, 0x4a, 0x39, 0x4d, 0x4d, 0x34, 0x48, 0x5a, 0x0a, 0x38, | |
0x36, 0x33, 0x31, 0x63, 0x70, 0x45, 0x6f, 0x72, 0x62, 0x4a, 0x71, 0x58, | |
0x33, 0x7a, 0x4f, 0x58, 0x6f, 0x47, 0x34, 0x58, 0x48, 0x45, 0x69, 0x34, | |
0x51, 0x62, 0x62, 0x57, 0x51, 0x43, 0x77, 0x4a, 0x4b, 0x4a, 0x68, 0x34, | |
0x79, 0x33, 0x37, 0x6d, 0x31, 0x31, 0x33, 0x4c, 0x66, 0x71, 0x32, 0x36, | |
0x65, 0x72, 0x35, 0x75, 0x38, 0x61, 0x68, 0x37, 0x79, 0x45, 0x30, 0x62, | |
0x4f, 0x34, 0x47, 0x0a, 0x66, 0x57, 0x37, 0x37, 0x6b, 0x54, 0x73, 0x44, | |
0x44, 0x68, 0x72, 0x61, 0x37, 0x58, 0x55, 0x36, 0x6b, 0x51, 0x57, 0x76, | |
0x41, 0x4a, 0x5a, 0x71, 0x63, 0x45, 0x36, 0x57, 0x44, 0x51, 0x75, 0x32, | |
0x41, 0x77, 0x61, 0x38, 0x62, 0x47, 0x6f, 0x32, 0x33, 0x2f, 0x54, 0x34, | |
0x38, 0x77, 0x48, 0x47, 0x66, 0x58, 0x74, 0x57, 0x4d, 0x43, 0x2b, 0x43, | |
0x54, 0x63, 0x2b, 0x68, 0x2f, 0x31, 0x73, 0x54, 0x0a, 0x33, 0x47, 0x53, | |
0x6e, 0x7a, 0x77, 0x55, 0x76, 0x52, 0x77, 0x31, 0x52, 0x2f, 0x46, 0x53, | |
0x43, 0x4c, 0x47, 0x76, 0x75, 0x53, 0x52, 0x38, 0x70, 0x0a, 0x2d, 0x2d, | |
0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, | |
0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x00 | |
}; | |
// ***************************** | |
//const char* ssid = WIFI_SSID; | |
//const char* password = WIFI_PASSWORD; | |
const char* ssid = "freeradius-2G"; | |
const char* password = "any_password_not_used"; | |
const char* otapassword = OTA_PASSWORD; | |
const char* mqttuser = MQTT_TEST_USER; | |
const char* mqttpass = MQTT_TEST_PASS; | |
IPAddress mqtt_server = MQTT_TEST_SERVER; | |
const char* fingerprint = "70 B2 BF 0D 4E 2A 54 FC DD C3 75 03 CD 42 20 71 9C 4A 97 37"; | |
//connecting to 192.168.10.144 | |
//certificate matches | |
// test | |
//const char* fingerprint = "70 B2 BF 0D 4E 2A 54 FC DD C3 75 03 CD 42 20 71 9C 4A 97 36"; | |
//connecting to 192.168.10.144 | |
//certificate doesn't match | |
//------------------------------- | |
char* topic = "pubtest"; | |
String clientName; | |
long lastReconnectAttempt = 0; | |
long lastMsg = 0; | |
int test_para = 2000; | |
unsigned long startMills; | |
//------------------------------ | |
WiFiClientSecure wifiClient; | |
//WiFiClient wifiClient; | |
PubSubClient client(mqtt_server, 8883, wifiClient); | |
//---------------------- | |
String macToStr(const uint8_t* mac); | |
void sendmqttMsg(char* topictosend, String payload); | |
void verifytls() { | |
// Use WiFiClientSecure class to create TLS connection | |
Serial.print("connecting to "); | |
Serial.println(mqtt_server); | |
if (!wifiClient.connect(mqtt_server, 8883)) { | |
Serial.println("connection failed"); | |
return; | |
} | |
if (wifiClient.verify(fingerprint, mqtt_server.toString().c_str())) { | |
Serial.println("certificate matches"); | |
} else { | |
Serial.println("certificate doesn't match"); | |
} | |
} | |
//----------------------- | |
boolean reconnect() | |
{ | |
if (!client.connected()) { | |
if (client.connect((char*) clientName.c_str(), mqttuser, mqttpass)) { | |
if (DEBUG_PRINT) { | |
Serial.println("===> mqtt connected"); | |
} | |
} else { | |
if (DEBUG_PRINT) { | |
Serial.print("---> mqtt failed, rc="); | |
Serial.println(client.state()); | |
} | |
} | |
} | |
return client.connected(); | |
} | |
void wifi_connect() | |
{ | |
if (WiFi.status() != WL_CONNECTED) { | |
// WIFI | |
if (DEBUG_PRINT) { | |
Serial.println(); | |
Serial.print("===> WIFI ---> Connecting to "); | |
Serial.println(ssid); | |
} | |
delay(10); | |
Serial.println("Cert set up"); | |
wifi_station_set_cert_key(espclient1_crt, sizeof(espclient1_crt), espclient1_key, sizeof(espclient1_key), NULL, 0); | |
Serial.println("Cert set done"); | |
Serial.println(""); | |
WiFi.mode(WIFI_STA); | |
WiFi.begin(ssid, password); | |
int Attempt = 0; | |
while (WiFi.status() != WL_CONNECTED) { | |
if (DEBUG_PRINT) { | |
Serial.print(". "); | |
Serial.print(Attempt); | |
} | |
delay(100); | |
Attempt++; | |
if (Attempt == 150) | |
{ | |
if (DEBUG_PRINT) { | |
Serial.println(); | |
Serial.println("-----> Could not connect to WIFI"); | |
} | |
ESP.restart(); | |
delay(200); | |
} | |
} | |
wifi_station_clear_cert_key(); | |
if (DEBUG_PRINT) { | |
Serial.println(); | |
Serial.print("===> WiFi connected"); | |
Serial.print(" ------> IP address: "); | |
Serial.println(WiFi.localIP()); | |
} | |
} | |
} | |
void setup() | |
{ | |
startMills = millis(); | |
if (DEBUG_PRINT) { | |
Serial.begin(115200); | |
} | |
wifi_connect(); | |
clientName += "esp8266-"; | |
uint8_t mac[6]; | |
WiFi.macAddress(mac); | |
clientName += macToStr(mac); | |
clientName += "-"; | |
clientName += String(micros() & 0xff, 16); | |
Serial.println(clientName); | |
verifytls(); | |
//OTA | |
// Port defaults to 8266 | |
//ArduinoOTA.setPort(8266); | |
// Hostname defaults to esp8266-[ChipID] | |
ArduinoOTA.setHostname("esp-test"); | |
// No authentication by default | |
ArduinoOTA.setPassword(otapassword); | |
ArduinoOTA.onStart([]() { | |
//Serial.println("Start"); | |
}); | |
ArduinoOTA.onEnd([]() { | |
//Serial.println("\nEnd"); | |
}); | |
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { | |
//Serial.printf("Progress: %u%%\r", (progress / (total / 100))); | |
}); | |
ArduinoOTA.onError([](ota_error_t error) { | |
ESP.restart(); | |
/* | |
if (error == OTA_AUTH_ERROR) abort(); | |
else if (error == OTA_BEGIN_ERROR) abort(); | |
else if (error == OTA_CONNECT_ERROR) abort(); | |
else if (error == OTA_RECEIVE_ERROR) abort(); | |
else if (error == OTA_END_ERROR) abort(); | |
*/ | |
}); | |
ArduinoOTA.begin(); | |
} | |
void loop() | |
{ | |
if (WiFi.status() == WL_CONNECTED) { | |
if (!client.connected()) { | |
long now = millis(); | |
if (now - lastReconnectAttempt > 2000) { | |
lastReconnectAttempt = now; | |
if (reconnect()) { | |
lastReconnectAttempt = 0; | |
} | |
} | |
} else { | |
long now = millis(); | |
if (now - lastMsg > test_para) { | |
lastMsg = now; | |
String payload = "{\"startMills\":"; | |
payload += (millis() - startMills); | |
payload += ",\"FreeHeap\":"; | |
payload += ESP.getFreeHeap(); | |
payload += ",\"RSSI\":"; | |
payload += WiFi.RSSI(); | |
payload += "}"; | |
sendmqttMsg(topic, payload); | |
} | |
client.loop(); | |
ArduinoOTA.handle(); | |
} | |
} else { | |
wifi_connect(); | |
} | |
} | |
void sendmqttMsg(char* topictosend, String payload) | |
{ | |
if (client.connected()) { | |
if (DEBUG_PRINT) { | |
Serial.print("Sending payload: "); | |
Serial.print(payload); | |
} | |
unsigned int msg_length = payload.length(); | |
if (DEBUG_PRINT) { | |
Serial.print(" length: "); | |
Serial.println(msg_length); | |
} | |
byte* p = (byte*)malloc(msg_length); | |
memcpy(p, (char*) payload.c_str(), msg_length); | |
if ( client.publish(topictosend, p, msg_length)) { | |
if (DEBUG_PRINT) { | |
Serial.println("Publish ok"); | |
} | |
free(p); | |
//return 1; | |
} else { | |
if (DEBUG_PRINT) { | |
Serial.println("Publish failed"); | |
} | |
free(p); | |
//return 0; | |
} | |
} | |
} | |
String macToStr(const uint8_t* mac) | |
{ | |
String result; | |
for (int i = 0; i < 6; ++i) { | |
result += String(mac[i], 16); | |
if (i < 5) | |
result += ':'; | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment