Beginnings of a slack example.
This commit is contained in:
parent
35d597c368
commit
cf56af61e3
|
@ -1 +1,2 @@
|
|||
*.swp
|
||||
credentials.h
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
Copyright (c) 2020 Brian Lough. All right reserved.
|
||||
|
||||
ArduinoSlack - An Arduino library to wrap the Slack API
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include "ArduinoSlack.h"
|
||||
|
||||
ArduinoSlack::ArduinoSlack(Client &client, const char *bearerToken)
|
||||
{
|
||||
this->client = &client;
|
||||
this->_bearerToken = bearerToken;
|
||||
}
|
||||
|
||||
int ArduinoSlack::makeGetRequest(const char *command, const char *body, const char *contentType)
|
||||
{
|
||||
client->flush();
|
||||
client->setTimeout(SLACK_TIMEOUT);
|
||||
if (!client->connect(SLACK_HOST, portNumber))
|
||||
{
|
||||
SLACK_SERIAL_LN(F("Connection failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// give the esp a breather
|
||||
yield();
|
||||
|
||||
// Send HTTP request
|
||||
client->print(F("GET "));
|
||||
client->print(command);
|
||||
client->println(F(" HTTP/1.1"));
|
||||
|
||||
//Headers
|
||||
client->print(F("Host: "));
|
||||
client->println(SLACK_HOST);
|
||||
|
||||
client->println(F("Accept: application/json"));
|
||||
client->print(F("Content-Type: "));
|
||||
client->println(contentType);
|
||||
|
||||
client->print(F("Authorization: Bearer "));
|
||||
client->println(_bearerToken);
|
||||
|
||||
client->println(F("Cache-Control: no-cache"));
|
||||
|
||||
client->print(F("Content-Length: "));
|
||||
client->println(strlen(body));
|
||||
|
||||
client->println();
|
||||
|
||||
//send Data here?
|
||||
client->print(body);
|
||||
|
||||
if (client->println() == 0)
|
||||
{
|
||||
SLACK_SERIAL_LN(F("Failed to send request"));
|
||||
return false;
|
||||
}
|
||||
|
||||
int statusCode = getHttpStatusCode();
|
||||
skipHeaders();
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
|
||||
int ArduinoSlack::makePostRequest(const char *command, const char *body, const char *contentType)
|
||||
{
|
||||
client->flush();
|
||||
client->setTimeout(SLACK_TIMEOUT);
|
||||
if (!client->connect(SLACK_HOST, portNumber))
|
||||
{
|
||||
SLACK_SERIAL_LN(F("Connection failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// give the esp a breather
|
||||
yield();
|
||||
|
||||
// Send HTTP request
|
||||
client->print(F("POST "));
|
||||
client->print(command);
|
||||
client->println(F(" HTTP/1.1"));
|
||||
|
||||
//Headers
|
||||
client->print(F("Host: "));
|
||||
client->println(SLACK_HOST);
|
||||
|
||||
client->println(F("Accept: application/json"));
|
||||
client->print(F("Content-Type: "));
|
||||
client->println(contentType);
|
||||
|
||||
client->print(F("Authorization: Bearer "));
|
||||
client->println(_bearerToken);
|
||||
|
||||
client->println(F("Cache-Control: no-cache"));
|
||||
|
||||
client->print(F("Content-Length: "));
|
||||
client->println(strlen(body));
|
||||
|
||||
client->println();
|
||||
|
||||
//send Data here?
|
||||
client->print(body);
|
||||
|
||||
if (client->println() == 0)
|
||||
{
|
||||
SLACK_SERIAL_LN(F("Failed to send request"));
|
||||
return false;
|
||||
}
|
||||
|
||||
int statusCode = getHttpStatusCode();
|
||||
skipHeaders();
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
bool ArduinoSlack::setPresence(const char *presence)
|
||||
{
|
||||
char command[100];
|
||||
sprintf(command, SLACK_USERS_SET_PRESENCE_ENDPOINT, presence);
|
||||
SLACK_DEBUG_SERIAL_LN(command);
|
||||
|
||||
// Get from https://arduinojson.org/v6/assistant/
|
||||
const size_t bufferSize = 1000;
|
||||
bool okStatus = false;
|
||||
if (makePostRequest(command, "", "text/plain") == 200)
|
||||
{
|
||||
// Allocate DynamicJsonDocument
|
||||
DynamicJsonDocument doc(bufferSize);
|
||||
|
||||
// Parse JSON object
|
||||
DeserializationError error = deserializeJson(doc, *client);
|
||||
if (!error)
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
|
||||
#ifdef SLACK_ENABLE_DEBUG
|
||||
serializeJson(doc, Serial);
|
||||
#endif
|
||||
okStatus = doc["ok"];
|
||||
if (!okStatus)
|
||||
{
|
||||
if (doc.containsKey("error"))
|
||||
{
|
||||
const char *errorMsg = doc["error"];
|
||||
SLACK_DEBUG_SERIAL(F("Got the following error: "));
|
||||
SLACK_DEBUG_SERIAL_LN(errorMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("Unkown Error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
|
||||
SLACK_DEBUG_SERIAL_LN(error.c_str());
|
||||
}
|
||||
}
|
||||
closeClient();
|
||||
return okStatus;
|
||||
}
|
||||
|
||||
SlackConvoHist ArduinoSlack::conversationHistory(const char *channel, const char *limit)
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("--------------"));
|
||||
SLACK_DEBUG_SERIAL_LN(F("conversationHistory()"));
|
||||
char body[300];
|
||||
sprintf(body, setConvoHistoryBody, channel, limit);
|
||||
SLACK_DEBUG_SERIAL_LN(body);
|
||||
|
||||
// Get from https://arduinojson.org/v6/assistant/
|
||||
const size_t bufferSize = profileBufferSize;
|
||||
|
||||
SlackConvoHist conversation;;
|
||||
// This flag will get cleared if all goes well
|
||||
conversation.error = true;
|
||||
if (makePostRequest(SLACK_CONVERSATIONS_HISTORY_ENDPOINT, body) == 200)
|
||||
{
|
||||
// Allocate DynamicJsonDocument
|
||||
DynamicJsonDocument doc(bufferSize);
|
||||
|
||||
// Parse JSON object
|
||||
DeserializationError error = deserializeJson(doc, *client);
|
||||
if (!error)
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
|
||||
#ifdef SLACK_ENABLE_DEBUG
|
||||
serializeJson(doc, Serial);
|
||||
#endif
|
||||
JsonObject messageObj = doc["messages"];
|
||||
conversation.messageObj = messageObj;
|
||||
|
||||
//message.text = (char *)messageObj["text"].as<char *>();
|
||||
//message.username = (char *)messageObj["username"].as<char *>();
|
||||
//message.bot_id = (char *)messageObj["bot_id"].as<char *>();
|
||||
//message.type = (char *)messageObj["type"].as<char *>();
|
||||
|
||||
conversation.error = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
|
||||
SLACK_DEBUG_SERIAL_LN(error.c_str());
|
||||
}
|
||||
}
|
||||
closeClient();
|
||||
return conversation;
|
||||
}
|
||||
|
||||
|
||||
SlackMessage ArduinoSlack::postMessage(const char *channel, const char *text)
|
||||
{
|
||||
char body[300];
|
||||
sprintf(body, setMessageBody, channel, text);
|
||||
SLACK_DEBUG_SERIAL_LN(body);
|
||||
|
||||
// Get from https://arduinojson.org/v6/assistant/
|
||||
const size_t bufferSize = profileBufferSize;
|
||||
|
||||
SlackMessage message;
|
||||
// This flag will get cleared if all goes well
|
||||
message.error = true;
|
||||
if (makePostRequest(SLACK_POST_MESSAGE_ENDPOINT, body) == 200)
|
||||
{
|
||||
// Allocate DynamicJsonDocument
|
||||
DynamicJsonDocument doc(bufferSize);
|
||||
|
||||
// Parse JSON object
|
||||
DeserializationError error = deserializeJson(doc, *client);
|
||||
if (!error)
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
|
||||
#ifdef SLACK_ENABLE_DEBUG
|
||||
serializeJson(doc, Serial);
|
||||
#endif
|
||||
JsonObject messageObj = doc["message"];
|
||||
|
||||
message.text = (char *)messageObj["text"].as<char *>();
|
||||
message.username = (char *)messageObj["username"].as<char *>();
|
||||
message.bot_id = (char *)messageObj["bot_id"].as<char *>();
|
||||
message.type = (char *)messageObj["type"].as<char *>();
|
||||
|
||||
message.error = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
|
||||
SLACK_DEBUG_SERIAL_LN(error.c_str());
|
||||
}
|
||||
}
|
||||
closeClient();
|
||||
return message;
|
||||
}
|
||||
|
||||
SlackProfile ArduinoSlack::setCustomStatus(const char *text, const char *emoji, int expiration)
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("setCustomStatus()"));
|
||||
char body[300];
|
||||
sprintf(body, setEndpointBody, text, emoji, expiration);
|
||||
SLACK_DEBUG_SERIAL_LN(body);
|
||||
|
||||
// Get from https://arduinojson.org/v6/assistant/
|
||||
const size_t bufferSize = profileBufferSize;
|
||||
|
||||
SlackProfile profile;
|
||||
// This flag will get cleared if all goes well
|
||||
profile.error = true;
|
||||
if (makePostRequest(SLACK_USERS_PROFILE_SET_ENDPOINT, body) == 200)
|
||||
{
|
||||
// Allocate DynamicJsonDocument
|
||||
DynamicJsonDocument doc(bufferSize);
|
||||
|
||||
// Parse JSON object
|
||||
DeserializationError error = deserializeJson(doc, *client);
|
||||
if (!error)
|
||||
{
|
||||
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
|
||||
#ifdef SLACK_ENABLE_DEBUG
|
||||
serializeJson(doc, Serial);
|
||||
#endif
|
||||
JsonObject profileObj = doc["profile"];
|
||||
|
||||
profile.displayName = (char *)profileObj["display_name"].as<char *>();
|
||||
profile.statusText = (char *)profileObj["status_text"].as<char *>();
|
||||
profile.statusEmoji = (char *)profileObj["status_emoji"].as<char *>();
|
||||
|
||||
profile.statusExpiration = profileObj["status_expiration"].as<int>();
|
||||
|
||||
profile.error = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
|
||||
SLACK_DEBUG_SERIAL_LN(error.c_str());
|
||||
}
|
||||
}
|
||||
closeClient();
|
||||
return profile;
|
||||
}
|
||||
|
||||
void ArduinoSlack::skipHeaders(bool tossUnexpectedForJSON)
|
||||
{
|
||||
// Skip HTTP headers
|
||||
if (!client->find("\r\n\r\n"))
|
||||
{
|
||||
SLACK_SERIAL_LN(F("Invalid response"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (tossUnexpectedForJSON)
|
||||
{
|
||||
// Was getting stray characters between the headers and the body
|
||||
// This should toss them away
|
||||
while (client->available() && client->peek() != '{')
|
||||
{
|
||||
char c = 0;
|
||||
client->readBytes(&c, 1);
|
||||
SLACK_DEBUG_SERIAL(F("Tossing an unexpected character: "));
|
||||
SLACK_DEBUG_SERIAL_LN(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ArduinoSlack::getHttpStatusCode()
|
||||
{
|
||||
// Check HTTP status
|
||||
if (client->find("HTTP/1.1"))
|
||||
{
|
||||
int statusCode = client->parseInt();
|
||||
SLACK_DEBUG_SERIAL(F("Status Code: "));
|
||||
SLACK_DEBUG_SERIAL_LN(statusCode);
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ArduinoSlack::closeClient()
|
||||
{
|
||||
if (client->connected())
|
||||
{
|
||||
|
||||
SLACK_DEBUG_SERIAL_LN(F("Closing client"));
|
||||
client->stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright (c) 2020 Brian Lough. All right reserved.
|
||||
|
||||
ArduinoSlack - An Arduino library to wrap the Slack API
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#ifndef ArduinoSlack_h
|
||||
#define ArduinoSlack_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Client.h>
|
||||
|
||||
#define SLACK_ENABLE_SERIAL
|
||||
|
||||
//un-mark following line to enable debug mode
|
||||
#define SLACK_ENABLE_DEBUG
|
||||
|
||||
#ifdef SLACK_ENABLE_SERIAL
|
||||
#define SLACK_SERIAL(STR) Serial.print(STR)
|
||||
#define SLACK_SERIAL_LN(STR) Serial.println(STR)
|
||||
#else
|
||||
#define SLACK_SERIAL(STR)
|
||||
#define SLACK_SERIAL_LN(STR)
|
||||
#endif
|
||||
|
||||
#ifdef SLACK_ENABLE_DEBUG
|
||||
#define SLACK_DEBUG_SERIAL(STR) Serial.print(STR)
|
||||
#define SLACK_DEBUG_SERIAL_LN(STR) Serial.println(STR)
|
||||
#else
|
||||
#define SLACK_DEBUG_SERIAL(STR)
|
||||
#define SLACK_DEBUG_SERIAL_LN(STR)
|
||||
#endif
|
||||
|
||||
#define SLACK_HOST "slack.com"
|
||||
// Fingerprint valid from Tue, 13 Apr 2021 00:00:00 GMT
|
||||
#define SLACK_FINGERPRINT "C3 CC ED 77 87 19 6D E7 76 5E AA A7 3D 67 7E CA 95 D2 46 E2"
|
||||
#define SLACK_TIMEOUT 2000
|
||||
|
||||
#define SLACK_PRESENCE_AWAY "away"
|
||||
#define SLACK_PRESENCE_AUTO "auto"
|
||||
|
||||
#define SLACK_USERS_PROFILE_SET_ENDPOINT "/api/users.profile.set"
|
||||
#define SLACK_USERS_SET_PRESENCE_ENDPOINT "/api/users.setPresence?presence=%s"
|
||||
#define SLACK_POST_MESSAGE_ENDPOINT "/api/chat.postMessage"
|
||||
#define SLACK_CONVERSATIONS_HISTORY_ENDPOINT "/api/conversations.history"
|
||||
|
||||
struct SlackProfile
|
||||
{
|
||||
char *displayName;
|
||||
char *statusText;
|
||||
char *statusEmoji;
|
||||
int statusExpiration;
|
||||
bool error;
|
||||
};
|
||||
|
||||
struct SlackMessage
|
||||
{
|
||||
char *text;
|
||||
char *username;
|
||||
char *bot_id;
|
||||
char *type;
|
||||
char *ts;
|
||||
bool error;
|
||||
};
|
||||
|
||||
struct SlackConvoHist
|
||||
{
|
||||
JsonObject messageObj;
|
||||
bool error;
|
||||
};
|
||||
|
||||
|
||||
class ArduinoSlack
|
||||
{
|
||||
public:
|
||||
ArduinoSlack(Client &client, const char *bearerToken);
|
||||
|
||||
int makePostRequest(const char *command, const char *body, const char *contentType = "application/json");
|
||||
SlackProfile setCustomStatus(const char *text, const char *emoji, int expiration = 0);
|
||||
SlackMessage postMessage(const char *channel, const char *text);
|
||||
SlackConvoHist conversationHistory(const char *channel, const char *limit);
|
||||
bool setPresence(const char *presence);
|
||||
int portNumber = 443;
|
||||
int profileBufferSize = 10000;
|
||||
Client *client;
|
||||
|
||||
private:
|
||||
const char *_bearerToken;
|
||||
int getHttpStatusCode();
|
||||
void skipHeaders(bool tossUnexpectedForJSON = true);
|
||||
void closeClient();
|
||||
|
||||
const char *setConvoHistoryBody =
|
||||
R"({"channel": "%s", "limit": "%s"})";
|
||||
const char *setMessageBody =
|
||||
R"({"channel": "%s", "text": "%s"})";
|
||||
const char *setEndpointBody =
|
||||
R"({"profile": { "status_text": "%s","status_emoji": "%s","status_expiration": %d}})";
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
// Digi Cert Global Root Cert - as of 26/08/2020
|
||||
// Useful for ESP32
|
||||
// Usage: client.setCACert(slack_server_cert);
|
||||
const char *slack_server_cert = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
||||
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
|
||||
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
|
||||
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
|
||||
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
|
||||
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
|
||||
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
|
||||
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
|
||||
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
|
||||
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
|
||||
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
|
||||
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
|
||||
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
|
||||
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
|
||||
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
|
||||
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
|
||||
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
|
||||
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
|
||||
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
|
@ -0,0 +1,151 @@
|
|||
/*******************************************************************
|
||||
Sets a custom status on your slack account. It will toggle between
|
||||
two every 30 seconds
|
||||
|
||||
You will need a bearer token, see readme for more details
|
||||
|
||||
Parts:
|
||||
ESP32 D1 Mini style Dev board* - http://s.click.aliexpress.com/e/C6ds4my
|
||||
|
||||
* * = Affiliate
|
||||
|
||||
If you find what I do useful and would like to support me,
|
||||
please consider becoming a sponsor on Github
|
||||
https://github.com/sponsors/witnessmenow/
|
||||
|
||||
|
||||
Written by Brian Lough
|
||||
YouTube: https://www.youtube.com/brianlough
|
||||
Tindie: https://www.tindie.com/stores/brianlough/
|
||||
Twitter: https://twitter.com/witnessmenow
|
||||
*******************************************************************/
|
||||
|
||||
// ----------------------------
|
||||
// Standard Libraries
|
||||
// ----------------------------
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
// ----------------------------
|
||||
// Additional Libraries - each one of these will need to be installed.
|
||||
// ----------------------------
|
||||
|
||||
#include "ArduinoSlack.h"
|
||||
// Library for connecting to the Slack API
|
||||
// Install from Github
|
||||
// https://github.com/witnessmenow/arduino-slack-api
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
// Library used for parsing Json from the API responses
|
||||
// Search for "Arduino Json" in the Arduino Library manager
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "credentials.h"
|
||||
// copy credentials.h.sample to credentials.h and edit
|
||||
// so it contains your passwords and tokens.
|
||||
|
||||
//------- Replace the following! ------
|
||||
|
||||
//char ssid[] = "SSID"; // your network SSID (name)
|
||||
//char password[] = "password"; // your network password
|
||||
char ssid[] = WIFI_SSID; // your network SSID (name)
|
||||
char password[] = WIFI_PASSWORD; // your network password
|
||||
|
||||
//#define SLACK_ACCESS_TOKEN "AAAAAAAAAABBBBBBBBBBBCCCCCCCCCCCDDDDDDDDDDD"
|
||||
|
||||
//------- ---------------------- ------
|
||||
|
||||
// including a "slack_server_cert" variable
|
||||
// header is included as part of the ArduinoSlack libary
|
||||
#include "ArduinoSlackCert.h"
|
||||
|
||||
WiFiClientSecure client;
|
||||
ArduinoSlack slack(client, SLACK_ACCESS_TOKEN);
|
||||
|
||||
unsigned long delayBetweenRequests = 120000; // Time between requests
|
||||
unsigned long requestDueTime; //time when request due
|
||||
|
||||
bool firstStatus = true;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
Serial.println("Wifi credentials:");
|
||||
Serial.println(ssid);
|
||||
Serial.println(password);
|
||||
Serial.print("Connecting to wifi.");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
client.setCACert(slack_server_cert);
|
||||
|
||||
// If you want to enable some extra debugging
|
||||
// uncomment the "#define SLACK_ENABLE_DEBUG" in ArduinoSlack.h
|
||||
}
|
||||
|
||||
void displayProfile(SlackProfile profile)
|
||||
{
|
||||
if (!profile.error)
|
||||
{
|
||||
Serial.println("--------- Profile ---------");
|
||||
|
||||
Serial.print("Display Name: ");
|
||||
Serial.println(profile.displayName);
|
||||
|
||||
Serial.print("Status Text: ");
|
||||
Serial.println(profile.statusText);
|
||||
|
||||
Serial.print("Status Emoji: ");
|
||||
Serial.println(profile.statusEmoji);
|
||||
|
||||
Serial.print("Status Expiration: ");
|
||||
Serial.println(profile.statusExpiration);
|
||||
|
||||
Serial.println("------------------------");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("error getting profile");
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (millis() > requestDueTime)
|
||||
{
|
||||
SlackProfile profile;
|
||||
SlackMessage message;
|
||||
if (firstStatus)
|
||||
{
|
||||
profile = slack.setCustomStatus("First status", ":apple:");
|
||||
message = slack.postMessage("equant-test", "This is a test message... :apple2:");
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = slack.setCustomStatus("And now the second status", ":apple2:");
|
||||
message = slack.postMessage("equant-test", "This is a different message... :cactus:");
|
||||
// There is an optional third parameter which takes a Unix timestamp for
|
||||
// when this custom status expires:
|
||||
// slack.setCustomStatus("I am the second status", ":v:", 1532627506);
|
||||
}
|
||||
firstStatus = !firstStatus;
|
||||
displayProfile(profile);
|
||||
requestDueTime = millis() + delayBetweenRequests;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
Use this program with the Apple2idIOT card and the basic programs RRAM, WRAM and CMDROT to read/write and rot13
|
||||
a single string contained within the dual port ram on the card.
|
||||
CA = 49664
|
||||
AA = CA + 1
|
||||
*/
|
||||
|
||||
// Load Wi-Fi library
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#include <Apple2Idiot.h>
|
||||
#include "ArduinoSlack.h"
|
||||
#include "credentials.h"
|
||||
#include "ArduinoSlackCert.h"
|
||||
// copy credentials.h.sample to credentials.h and edit
|
||||
// so it contains your passwords and tokens.
|
||||
|
||||
Apple2Idiot a2i = Apple2Idiot();
|
||||
|
||||
WiFiClientSecure client;
|
||||
ArduinoSlack slack(client, SLACK_ACCESS_TOKEN);
|
||||
|
||||
#define COMMAND_SET_CHANNEL 200
|
||||
#define COMMAND_SEND_MESSAGE 201
|
||||
#define COMMAND_GET_CHANNEL_MESSAGES 202
|
||||
|
||||
char wifi_ssid[] = WIFI_SSID; // your network SSID (name)
|
||||
char wifi_password[] = WIFI_PASSWORD; // your network password
|
||||
|
||||
/*******************/
|
||||
/* Misc */
|
||||
/*******************/
|
||||
|
||||
const long readLoopInterval = 100; // millis
|
||||
unsigned long lastReadLoopTime = 0;
|
||||
|
||||
byte lastAppleCommand = 0;
|
||||
|
||||
/*################################################
|
||||
# Setup #
|
||||
################################################*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
a2i.init();
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("Starting wifi...");
|
||||
Serial.print(" connecting to: ");
|
||||
Serial.println(wifi_ssid);
|
||||
|
||||
WiFi.begin(wifi_ssid, wifi_password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(600);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected successfully");
|
||||
Serial.print("Got IP: ");
|
||||
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
|
||||
client.setCACert(slack_server_cert);
|
||||
|
||||
Serial.println("Setup done");
|
||||
}
|
||||
|
||||
/*################################################
|
||||
# Functions #
|
||||
################################################*/
|
||||
|
||||
|
||||
/*################################################
|
||||
# Main #
|
||||
################################################*/
|
||||
|
||||
//String channel_name = "equant-test";
|
||||
String channel_name = "C02EAQECY5A";
|
||||
String message = "";
|
||||
SlackConvoHist conversation;
|
||||
|
||||
void loop() {
|
||||
|
||||
if ((millis() - lastReadLoopTime) > readLoopInterval) {
|
||||
byte command_byte = a2i.read_data(APPLE_COMMAND_ADDRESS);
|
||||
if (command_byte == RAM_BUSY) {
|
||||
Serial.println("Command Read: RAM BUSY");
|
||||
}
|
||||
else if (command_byte != lastAppleCommand){
|
||||
byte result = 0;
|
||||
Serial.print("Command Switch command_byte: ");
|
||||
Serial.println(command_byte);
|
||||
switch(command_byte) {
|
||||
case COMMAND_GET_CHANNEL_MESSAGES:
|
||||
Serial.println("COMMAND_GET_CHANNEL_MESSAGES");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
char cc[250];
|
||||
channel_name.toCharArray(cc, 250);
|
||||
conversation = slack.conversationHistory(cc, "2");
|
||||
serializeJsonPretty(conversation.messageObj, Serial);
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
case COMMAND_SET_CHANNEL:
|
||||
Serial.println("COMMAND_SET_CHANNEL");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
channel_name = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received: ["+channel_name+"]");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
case COMMAND_SEND_MESSAGE:
|
||||
Serial.println("COMMAND_SEND_MESSAGE:");
|
||||
SlackMessage slackMessage;
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
message = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
char m[250];
|
||||
message.toCharArray(m, 250);
|
||||
char c[250];
|
||||
channel_name.toCharArray(c, 250);
|
||||
slackMessage = slack.postMessage(c, m);
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
}
|
||||
lastAppleCommand = command_byte;
|
||||
}
|
||||
lastReadLoopTime = millis();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
Use this program with the Apple2idIOT card and the basic programs RRAM, WRAM and CMDROT to read/write and rot13
|
||||
a single string contained within the dual port ram on the card.
|
||||
CA = 49664
|
||||
AA = CA + 1
|
||||
*/
|
||||
|
||||
// Load Wi-Fi library
|
||||
#include <WiFi.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
Apple2Idiot a2i = Apple2Idiot();
|
||||
|
||||
#define COMMAND_SET_COUNTRY 200
|
||||
#define COMMAND_SET_CITY 201
|
||||
#define COMMAND_FETCH_WEATHER 205
|
||||
|
||||
const char* wifi_ssid = "GSO";
|
||||
const char* wifi_password = "xerxes27";
|
||||
|
||||
/*******************/
|
||||
/* Weather Service */
|
||||
/*******************/
|
||||
|
||||
const String weather_service_api_key= "0ab97bbbea58592d7c9d64067a34d2d0";
|
||||
const String weather_url = "http://api.openweathermap.org/data/2.5/weather?";
|
||||
|
||||
/*******************/
|
||||
/* Misc */
|
||||
/*******************/
|
||||
|
||||
const long readLoopInterval = 100; // millis
|
||||
unsigned long lastReadLoopTime = 0;
|
||||
|
||||
byte lastAppleCommand = 0;
|
||||
|
||||
/*################################################
|
||||
# Setup #
|
||||
################################################*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
a2i.init();
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("Starting wifi...");
|
||||
Serial.print(" connecting to: ");
|
||||
Serial.println(wifi_ssid);
|
||||
|
||||
WiFi.begin(wifi_ssid, wifi_password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(600);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected successfully");
|
||||
Serial.print("Got IP: ");
|
||||
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
|
||||
|
||||
Serial.println("Setup done");
|
||||
}
|
||||
|
||||
/*################################################
|
||||
# Functions #
|
||||
################################################*/
|
||||
|
||||
byte fetch_weather(char* city_name) {
|
||||
|
||||
byte result = 0;
|
||||
HTTPClient http;
|
||||
const String request_url = weather_url + "q=Tucson,us&APPID=" + weather_service_api_key;
|
||||
Serial.println(request_url);
|
||||
http.begin(request_url);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
String payload = http.getString();
|
||||
//Serial.println(httpCode);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
Serial.println(payload);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<200> filter;
|
||||
filter["weather"][0]["main"] = true;
|
||||
filter["weather"][0]["description"] = true;
|
||||
filter["main"]["humidity"] = true;
|
||||
filter["main"]["temp"] = true;
|
||||
filter["wind"]["speed"] = true;
|
||||
filter["wind"]["deg"] = true;
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
|
||||
//DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
} else {
|
||||
//const char* main = doc["main"];
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc["wind"], Serial);
|
||||
Serial.println("----------------------");
|
||||
//int temp = doc["main"]["temp"];
|
||||
//int humidity = doc["main"]["humidity"];
|
||||
//float wind_speed = doc["wind"]["speed"];
|
||||
//int wind_deg = doc["wind"]["deg"];
|
||||
//String weather_description = doc["weather"][0]["description"];
|
||||
//a2i.write_data(0, round(temp-273.15));
|
||||
//a2i.write_data(1, round(humidity));
|
||||
//a2i.write_data(2, round(wind_deg/10)); // divide by twn because 360 is too big for 8 bits
|
||||
//a2i.write_data(3, round(wind_speed));
|
||||
String temp = doc["main"]["temp"];
|
||||
String humidity = doc["main"]["humidity"];
|
||||
String wind_speed = doc["wind"]["speed"];
|
||||
String wind_deg = doc["wind"]["deg"];
|
||||
String weather_description = doc["weather"][0]["description"];
|
||||
int address_counter = a2i.write_string_to_shared_ram(temp, SHARED_RAM_START_ADDRESS);
|
||||
address_counter = a2i.write_string_to_shared_ram(humidity, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(wind_speed, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(wind_deg, address_counter + 1);
|
||||
}
|
||||
result = ACK;
|
||||
}
|
||||
else {
|
||||
Serial.println("Error on HTTP request");
|
||||
result = ERR;
|
||||
}
|
||||
|
||||
http.end(); //Free the resources
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*################################################
|
||||
# Main #
|
||||
################################################*/
|
||||
|
||||
void loop() {
|
||||
|
||||
if ((millis() - lastReadLoopTime) > readLoopInterval) {
|
||||
byte command_byte = a2i.read_data(APPLE_COMMAND_ADDRESS);
|
||||
if (command_byte == RAM_BUSY) {
|
||||
Serial.println("Command Read: RAM BUSY");
|
||||
}
|
||||
else if (command_byte != lastAppleCommand){
|
||||
byte result = 0;
|
||||
Serial.print("Command Switch command_byte: ");
|
||||
Serial.println(command_byte);
|
||||
switch(command_byte) {
|
||||
case COMMAND_SET_COUNTRY:
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
//int access_point_n = a2i.read_data(SHARED_RAM_START_ADDRESS) - 1;
|
||||
//String password_as_String = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
|
||||
//a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
break;
|
||||
case COMMAND_SET_CITY:
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
//int access_point_n = a2i.read_data(SHARED_RAM_START_ADDRESS) - 1;
|
||||
//String password_as_String = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
|
||||
//a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
break;
|
||||
case COMMAND_FETCH_WEATHER:
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
result = fetch_weather("Tucson");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
}
|
||||
lastAppleCommand = command_byte;
|
||||
}
|
||||
lastReadLoopTime = millis();
|
||||
}
|
||||
}
|
|
@ -1,194 +1,44 @@
|
|||
/*
|
||||
|
||||
Use this program with the Apple2idIOT card and the basic programs RRAM, WRAM and CMDROT to read/write and rot13
|
||||
a single string contained within the dual port ram on the card.
|
||||
|
||||
CA = 49664
|
||||
AA = CA + 1
|
||||
*/
|
||||
|
||||
#define DEBUG true
|
||||
|
||||
// Load Wi-Fi library
|
||||
#include <WiFi.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
/**********************/
|
||||
/* Default WiFi */
|
||||
/**********************/
|
||||
Apple2Idiot a2i = Apple2Idiot();
|
||||
|
||||
// Replace with your network credentials
|
||||
const char* wifi_ssid = "ella";
|
||||
const char* wifi_password = "";
|
||||
#define COMMAND_SET_COUNTRY 200
|
||||
#define COMMAND_SET_CITY 201
|
||||
#define COMMAND_FETCH_WEATHER 205
|
||||
|
||||
/**************/
|
||||
/* ESP32 Pins */
|
||||
/**************/
|
||||
const char* wifi_ssid = "GSO";
|
||||
const char* wifi_password = "xerxes27";
|
||||
|
||||
/* DATA BUS (numbers mean GPIO port) */
|
||||
#define D0R 12
|
||||
#define D1R 13
|
||||
#define D2R 14
|
||||
#define D3R 15
|
||||
#define D4R 16
|
||||
#define D5R 17
|
||||
#define D6R 18
|
||||
#define D7R 19
|
||||
byte data_pins[] = {D7R, D6R, D5R, D4R, D3R, D2R, D1R, D0R};
|
||||
#define DATA_BUS_SIZE 8
|
||||
/*******************/
|
||||
/* Weather Service */
|
||||
/*******************/
|
||||
|
||||
/* Address Bus */
|
||||
#define A0R 21
|
||||
#define A1R 22
|
||||
#define A2R 23
|
||||
#define A3R 25
|
||||
#define A4R 26
|
||||
#define A5R 27
|
||||
#define A6R 32
|
||||
#define A7R 33
|
||||
byte address_pins[] = {A0R, A1R, A2R, A3R, A4R, A5R, A6R, A7R};
|
||||
#define ADDRESS_BUS_SIZE 8
|
||||
#define ESP_COMMAND_ADDRESS 0
|
||||
#define APPLE_COMMAND_ADDRESS 1
|
||||
#define SHARED_RAM_START_ADDRESS 2
|
||||
#define RAM_BUSY 666
|
||||
#define MAX_STR_LEN 44 // arbitrary length.
|
||||
const String weather_service_api_key= "0ab97bbbea58592d7c9d64067a34d2d0";
|
||||
const String weather_url = "http://api.openweathermap.org/data/2.5/weather?";
|
||||
|
||||
#define COMMAND_GENERIC 0b10000000
|
||||
#define COMMAND_SCAN_WIFI 111
|
||||
#define COMMAND_CONNECT 112
|
||||
String country_code = "US";
|
||||
String city_name = "Tucson";
|
||||
|
||||
/* IDT7132S dual port ram chip enable */
|
||||
#define RW_PIN 5
|
||||
#define RW_WRITE LOW
|
||||
#define RW_READ HIGH
|
||||
|
||||
#define INPUT_35 35
|
||||
#define INPUT_34 34
|
||||
|
||||
#define ETX 3 // ASCII "End of Text" (ETX) character
|
||||
#define ACK 0b00000110 // Acknowledge
|
||||
#define EOT 0b00000100 // End of transmit
|
||||
|
||||
/*********/
|
||||
/* Misc. */
|
||||
/*********/
|
||||
/*******************/
|
||||
/* Misc */
|
||||
/*******************/
|
||||
|
||||
const long readLoopInterval = 100; // millis
|
||||
unsigned long lastReadLoopTime = 0;
|
||||
byte ram[256];
|
||||
volatile byte ram_busy=0;
|
||||
|
||||
byte lastAppleCommand = 0;
|
||||
|
||||
/*################################################
|
||||
# Functions #
|
||||
################################################*/
|
||||
|
||||
void unbusy_ram() {
|
||||
set_address(ESP_COMMAND_ADDRESS);
|
||||
ram_busy = false;
|
||||
}
|
||||
|
||||
boolean set_address(int address) {
|
||||
if (ram_busy) {
|
||||
Serial.println("BUSY");
|
||||
return false;
|
||||
}
|
||||
ram_busy = true;
|
||||
for (byte i=0; i<ADDRESS_BUS_SIZE; i++) {
|
||||
byte state = bitRead(address, i);
|
||||
digitalWrite(address_pins[i], state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
byte read_data(int address) {
|
||||
byte data_bus_read = 0;
|
||||
if (set_address(address)) {
|
||||
digitalWrite(RW_PIN, RW_READ); // Should already be set to RW_READ, but just in case.
|
||||
for (byte i=0; i<DATA_BUS_SIZE; i++) {
|
||||
byte pin_state = digitalRead(data_pins[i]);
|
||||
data_bus_read += pin_state * pow(2,i);
|
||||
}
|
||||
ram_busy = false;
|
||||
unbusy_ram();
|
||||
return data_bus_read;
|
||||
} else {
|
||||
return RAM_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean write_data(byte address, byte byte_to_write) {
|
||||
Serial.print("WRITE: ");
|
||||
Serial.print(byte_to_write);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(address);
|
||||
if (set_address(address)) {
|
||||
//set_address(address);
|
||||
Serial.print(" D:");
|
||||
for (byte i=0; i<DATA_BUS_SIZE; i++) {
|
||||
byte bit_to_write = (byte_to_write >> i) & 0b00000001;
|
||||
pinMode(data_pins[i], OUTPUT);
|
||||
digitalWrite(data_pins[i], bit_to_write);
|
||||
Serial.print(bit_to_write);
|
||||
}
|
||||
Serial.println();
|
||||
digitalWrite(RW_PIN, RW_WRITE);
|
||||
delay(1);
|
||||
digitalWrite(RW_PIN, RW_READ);
|
||||
for (byte i=0; i<DATA_BUS_SIZE; i++) {
|
||||
pinMode(data_pins[i], INPUT);
|
||||
}
|
||||
unbusy_ram();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int write_string_to_shared_ram(String string_to_send, unsigned int address) {
|
||||
//if (string_to_send.length() > 15 - 1) { // - 1 because of null character at end of string.
|
||||
write_data(ESP_COMMAND_ADDRESS, 12);
|
||||
unsigned int c = 0;
|
||||
for (c=0; c < string_to_send.length(); c++) {
|
||||
Serial.print("A(");
|
||||
Serial.print(c);
|
||||
Serial.print("): ");
|
||||
Serial.println(string_to_send[c]);
|
||||
write_data(address+c, string_to_send[c]);
|
||||
}
|
||||
write_data(address+c, ETX);
|
||||
//write_data(15, COMMAND_FROM_ESP + command_message + COMMAND_NO_DATA_WAITING);
|
||||
write_data(ESP_COMMAND_ADDRESS, 27);
|
||||
return address+c;
|
||||
}
|
||||
|
||||
String read_string_from_ram(int address) {
|
||||
byte c = 0;
|
||||
int i = 0;
|
||||
String read_string = "";
|
||||
while ( (i<MAX_STR_LEN) && (c!=ETX) ) {
|
||||
c = read_data(address+i);
|
||||
read_string = read_string + char(c);
|
||||
i++;
|
||||
}
|
||||
Serial.print("READ STRING:");
|
||||
Serial.println(read_string);
|
||||
return read_string;
|
||||
}
|
||||
|
||||
void read_ram(int size_to_read=256);
|
||||
void read_ram(int size_to_read) {
|
||||
for (int i=0; i < size_to_read; i++) {
|
||||
unsigned int foo = read_data(i);
|
||||
ram[i] = foo;
|
||||
Serial.print(i);
|
||||
Serial.print(" ");
|
||||
Serial.println(foo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*################################################
|
||||
# Setup #
|
||||
################################################*/
|
||||
|
@ -196,27 +46,7 @@ void read_ram(int size_to_read) {
|
|||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
/* Configure ESP32 Pins */
|
||||
pinMode(A0R, OUTPUT); digitalWrite(A0R, LOW);
|
||||
pinMode(A1R, OUTPUT); digitalWrite(A1R, LOW);
|
||||
pinMode(A2R, OUTPUT); digitalWrite(A2R, LOW);
|
||||
pinMode(A3R, OUTPUT); digitalWrite(A3R, LOW);
|
||||
pinMode(A4R, OUTPUT); digitalWrite(A4R, LOW);
|
||||
pinMode(A5R, OUTPUT); digitalWrite(A5R, LOW);
|
||||
pinMode(A6R, OUTPUT); digitalWrite(A6R, LOW);
|
||||
pinMode(A7R, OUTPUT); digitalWrite(A7R, LOW);
|
||||
pinMode(D0R, INPUT);
|
||||
pinMode(D1R, INPUT);
|
||||
pinMode(D2R, INPUT);
|
||||
pinMode(D3R, INPUT);
|
||||
pinMode(D4R, INPUT);
|
||||
pinMode(D5R, INPUT);
|
||||
pinMode(D6R, INPUT);
|
||||
pinMode(D7R, INPUT);
|
||||
pinMode(RW_PIN, OUTPUT); digitalWrite(RW_PIN, RW_READ);
|
||||
|
||||
pinMode(INPUT_34, INPUT);
|
||||
pinMode(INPUT_35, INPUT);
|
||||
a2i.init();
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("Starting wifi...");
|
||||
|
@ -225,7 +55,7 @@ void setup() {
|
|||
|
||||
WiFi.begin(wifi_ssid, wifi_password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(900);
|
||||
delay(600);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
|
@ -234,117 +64,115 @@ void setup() {
|
|||
Serial.print("Got IP: ");
|
||||
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
|
||||
|
||||
// Set WiFi to station mode and disconnect from an AP if it was previously connected
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
delay(10);
|
||||
|
||||
write_string_to_shared_ram("Starting Up!", SHARED_RAM_START_ADDRESS);
|
||||
write_data(ESP_COMMAND_ADDRESS, ACK);
|
||||
write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
|
||||
Serial.println("Setup done");
|
||||
}
|
||||
|
||||
/*################################################
|
||||
# Functions #
|
||||
################################################*/
|
||||
|
||||
byte fetch_weather() {
|
||||
|
||||
byte result = 0;
|
||||
HTTPClient http;
|
||||
//const String request_url = weather_url + "q=Tucson,us&APPID=" + weather_service_api_key;
|
||||
const String request_url = weather_url + "q=" + city_name + "," + country_code + "&APPID=" + weather_service_api_key;
|
||||
Serial.println(request_url);
|
||||
http.begin(request_url);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
String payload = http.getString();
|
||||
//Serial.println(httpCode);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
Serial.println(payload);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<200> filter;
|
||||
filter["weather"][0]["main"] = true;
|
||||
filter["weather"][0]["description"] = true;
|
||||
filter["main"]["humidity"] = true;
|
||||
filter["main"]["temp"] = true;
|
||||
filter["wind"]["speed"] = true;
|
||||
filter["wind"]["deg"] = true;
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
|
||||
//DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc["wind"], Serial);
|
||||
Serial.println("----------------------");
|
||||
String temp = doc["main"]["temp"];
|
||||
String humidity = doc["main"]["humidity"];
|
||||
String wind_speed = doc["wind"]["speed"];
|
||||
String wind_deg = doc["wind"]["deg"];
|
||||
String weather_description1 = doc["weather"][0]["main"];
|
||||
String weather_description2 = doc["weather"][0]["description"];
|
||||
int address_counter = a2i.write_string_to_shared_ram(temp, SHARED_RAM_START_ADDRESS);
|
||||
address_counter = a2i.write_string_to_shared_ram(humidity, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(wind_speed, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(wind_deg, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(weather_description1, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(weather_description2, address_counter + 1);
|
||||
}
|
||||
result = ACK;
|
||||
}
|
||||
else {
|
||||
Serial.println("Error on HTTP request");
|
||||
result = ERR;
|
||||
}
|
||||
|
||||
http.end(); //Free the resources
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*################################################
|
||||
# Main #
|
||||
################################################*/
|
||||
|
||||
void scan_wifi() {
|
||||
Serial.println("scan start");
|
||||
|
||||
// WiFi.scanNetworks will return the number of networks found
|
||||
int n = WiFi.scanNetworks();
|
||||
Serial.println("scan done");
|
||||
int address_counter = SHARED_RAM_START_ADDRESS + 1;
|
||||
if (n == 0) {
|
||||
Serial.println("no networks found");
|
||||
write_data(0, address_counter);
|
||||
} else {
|
||||
Serial.print(n);
|
||||
Serial.println(" networks found");
|
||||
write_data(n, address_counter);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
// Print SSID and RSSI for each network found
|
||||
Serial.print(i + 1);
|
||||
Serial.print(": ");
|
||||
Serial.print(WiFi.SSID(i));
|
||||
Serial.print(" (");
|
||||
Serial.print(WiFi.RSSI(i));
|
||||
Serial.print(")");
|
||||
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
|
||||
delay(10);
|
||||
address_counter = write_string_to_shared_ram(WiFi.SSID(i), address_counter + 1);
|
||||
//address_counter = write_string_to_shared_ram(String(WiFi.RSSI(i)), address_counter + 1);
|
||||
//address_counter = write_string_to_shared_ram(WiFi.encryptionType(i), address_counter + 1);
|
||||
}
|
||||
}
|
||||
write_data(ESP_COMMAND_ADDRESS, EOT);
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
void store_ip_to_ram(byte offset) {
|
||||
IPAddress ip_address = WiFi.localIP();
|
||||
//for (int i=0; i < ADDRESS_BUS_SIZE; i++) {
|
||||
for (int i=0; i < 4; i++) {
|
||||
write_data(i+offset, ip_address[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const char* wifi_ssid = "";
|
||||
const char* wifi_password = "";
|
||||
|
||||
void loop() {
|
||||
|
||||
if ((millis() - lastReadLoopTime) > readLoopInterval) {
|
||||
byte command_byte = read_data(APPLE_COMMAND_ADDRESS);
|
||||
byte command_byte = a2i.read_data(APPLE_COMMAND_ADDRESS);
|
||||
if (command_byte == RAM_BUSY) {
|
||||
Serial.println("Command Read: RAM BUSY");
|
||||
}
|
||||
else if (command_byte != lastAppleCommand){
|
||||
byte result = 0;
|
||||
Serial.print("Command Switch command_byte: ");
|
||||
Serial.println(command_byte);
|
||||
switch(command_byte) {
|
||||
case COMMAND_SCAN_WIFI:
|
||||
write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
//String read_string = read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
//write_string_to_shared_ram(rot13(read_string), SHARED_RAM_START_ADDRESS);
|
||||
scan_wifi();
|
||||
write_data(APPLE_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
case COMMAND_SET_COUNTRY:
|
||||
Serial.println("COMMAND_SET_COUNTRY");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
country_code = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received: ["+country_code+"]");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
}
|
||||
switch(command_byte) {
|
||||
case COMMAND_CONNECT:
|
||||
write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
int access_point_n = read_data(SHARED_RAM_START_ADDRESS);
|
||||
String ssid_as_String = WiFi.SSID(access_point_n);
|
||||
String password_as_String = read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
|
||||
wifi_password = password_as_String.c_str();
|
||||
wifi_ssid = ssid_as_String.c_str();
|
||||
//wifi_password = read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
|
||||
//wifi_ssid = WiFi.SSID(access_point_n);
|
||||
//WiFi.begin(wifi_ssid, wifi_password);
|
||||
Serial.print("password:");
|
||||
Serial.println(password_as_String);
|
||||
Serial.print("password:(");
|
||||
Serial.print(wifi_password);
|
||||
Serial.println(")");
|
||||
//WiFi.begin(wifi_ssid, wifi_password);
|
||||
WiFi.begin("GSO", "xerxes27");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(300);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected successfully");
|
||||
Serial.print("Got IP: ");
|
||||
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
|
||||
store_ip_to_ram(SHARED_RAM_START_ADDRESS);
|
||||
write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
case COMMAND_SET_CITY:
|
||||
Serial.println("COMMAND_SET_CITY");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
city_name = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received: ["+city_name+"]");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
case COMMAND_FETCH_WEATHER:
|
||||
Serial.println("COMMAND_FETCH_WEATHER");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
result = fetch_weather();
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
|
||||
break;
|
||||
}
|
||||
lastAppleCommand = command_byte;
|
||||
write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
}
|
||||
lastReadLoopTime = millis();
|
||||
}
|
||||
|
|
|
@ -79,14 +79,12 @@ void loop() {
|
|||
Serial.print("Command Switch command_byte: ");
|
||||
Serial.println(command_byte);
|
||||
switch(command_byte) {
|
||||
case COMMAND_SCAN_WIFI:
|
||||
case COMMAND_WIFI_SCAN:
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
scan_wifi();
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
break;
|
||||
}
|
||||
switch(command_byte) {
|
||||
case COMMAND_CONNECT:
|
||||
case COMMAND_WIFI_CONNECT:
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
int access_point_n = a2i.read_data(SHARED_RAM_START_ADDRESS) - 1;
|
||||
String ssid_as_String = WiFi.SSID(access_point_n);
|
||||
|
|
|
@ -43,7 +43,7 @@ void Apple2Idiot::unbusy_ram() {
|
|||
|
||||
boolean Apple2Idiot::set_address(int address) {
|
||||
if (ram_busy) {
|
||||
Serial.println("BUSY");
|
||||
//Serial.println("BUSY");
|
||||
return false;
|
||||
}
|
||||
ram_busy = true;
|
||||
|
@ -78,14 +78,14 @@ boolean Apple2Idiot::write_data(byte address, byte byte_to_write) {
|
|||
Serial.println(address);
|
||||
if (set_address(address)) {
|
||||
//set_address(address);
|
||||
Serial.print(" D:");
|
||||
//Serial.print(" D:");
|
||||
for (byte i=0; i<DATA_BUS_SIZE; i++) {
|
||||
byte bit_to_write = (byte_to_write >> i) & 0b00000001;
|
||||
pinMode(data_pins[i], OUTPUT);
|
||||
digitalWrite(data_pins[i], bit_to_write);
|
||||
Serial.print(bit_to_write);
|
||||
//Serial.print(bit_to_write);
|
||||
}
|
||||
Serial.println();
|
||||
//Serial.println();
|
||||
digitalWrite(RW_PIN, RW_WRITE);
|
||||
delay(1);
|
||||
digitalWrite(RW_PIN, RW_READ);
|
||||
|
@ -123,7 +123,9 @@ String Apple2Idiot::read_string_from_ram(int address) {
|
|||
String read_string = "";
|
||||
while ( (i<MAX_STR_LEN) && (c!=ETX) ) {
|
||||
c = read_data(address+i);
|
||||
read_string = read_string + char(c);
|
||||
if (c!=ETX) {
|
||||
read_string = read_string + char(c);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
Serial.print("READ STRING:");
|
||||
|
|
|
@ -23,15 +23,31 @@
|
|||
#define A6R 32
|
||||
#define A7R 33
|
||||
#define ADDRESS_BUS_SIZE 8
|
||||
|
||||
#define ESP_COMMAND_ADDRESS 0
|
||||
#define APPLE_COMMAND_ADDRESS 1
|
||||
#define SHARED_RAM_START_ADDRESS 2
|
||||
#define RAM_BUSY 666
|
||||
#define MAX_STR_LEN 44 // arbitrary length.
|
||||
#define MAX_STR_LEN 250 // arbitrary length.
|
||||
|
||||
#define COMMAND_GENERIC 0b10000000
|
||||
#define COMMAND_SCAN_WIFI 111
|
||||
#define COMMAND_CONNECT 112
|
||||
//
|
||||
// Commands and messages that are communicated between the ESP and the Apple
|
||||
// via the dual-port ram.
|
||||
//
|
||||
// Commands >=200 are "non-reserved", and are meant
|
||||
// to be defined within scipts that use this library.
|
||||
// So anything in this library should be below 200.
|
||||
//
|
||||
// If the values of these defines are changed, then they will need to be
|
||||
// updated within the code that runs on the Apple as well.
|
||||
|
||||
//#define COMMAND_GENERIC 0b10000000
|
||||
#define COMMAND_WIFI_SCAN 111
|
||||
#define COMMAND_WIFI_CONNECT 112
|
||||
#define ACK 0b00000110 // Acknowledge
|
||||
#define EOT 0b00000100 // End of transmit
|
||||
#define ERR 0b00000101 // Error
|
||||
#define MORE_TO_SEND 0b00000111
|
||||
|
||||
/* IDT7132S dual port ram chip enable */
|
||||
#define RW_PIN 5
|
||||
|
@ -39,8 +55,6 @@
|
|||
#define RW_READ HIGH
|
||||
|
||||
#define ETX 3 // ASCII "End of Text" (ETX) character
|
||||
#define ACK 0b00000110 // Acknowledge
|
||||
#define EOT 0b00000100 // End of transmit
|
||||
|
||||
#define INPUT_35 35
|
||||
#define INPUT_34 34
|
||||
|
|
Loading…
Reference in New Issue