From cf56af61e30312f94e718ab0bc49d3969c9dae2c Mon Sep 17 00:00:00 2001 From: Nathanial Hendler Date: Sat, 11 Sep 2021 16:48:28 -0700 Subject: [PATCH 1/4] Beginnings of a slack example. --- .gitignore | 1 + examples/foo/{weather.ino => foo.ino} | 0 examples/slack/ArduinoSlack.cpp | 348 +++++++++++++++++++++++ examples/slack/ArduinoSlack.h | 104 +++++++ examples/slack/ArduinoSlackCert.h | 25 ++ examples/slack/myTest.ino.old | 151 ++++++++++ examples/slack/slack.ino | 133 +++++++++ examples/weather/; | 177 ++++++++++++ examples/weather/weather.ino | 394 ++++++++------------------ examples/wifi_scan/wifi_scan.ino | 6 +- lib/Apple2Idiot/Apple2Idiot.cpp | 12 +- lib/Apple2Idiot/Apple2Idiot.h | 26 +- notes.md | 4 + 13 files changed, 1083 insertions(+), 298 deletions(-) rename examples/foo/{weather.ino => foo.ino} (100%) create mode 100644 examples/slack/ArduinoSlack.cpp create mode 100644 examples/slack/ArduinoSlack.h create mode 100644 examples/slack/ArduinoSlackCert.h create mode 100644 examples/slack/myTest.ino.old create mode 100644 examples/slack/slack.ino create mode 100644 examples/weather/; diff --git a/.gitignore b/.gitignore index 1377554..02694f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.swp +credentials.h diff --git a/examples/foo/weather.ino b/examples/foo/foo.ino similarity index 100% rename from examples/foo/weather.ino rename to examples/foo/foo.ino diff --git a/examples/slack/ArduinoSlack.cpp b/examples/slack/ArduinoSlack.cpp new file mode 100644 index 0000000..9fe4af0 --- /dev/null +++ b/examples/slack/ArduinoSlack.cpp @@ -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(); + //message.username = (char *)messageObj["username"].as(); + //message.bot_id = (char *)messageObj["bot_id"].as(); + //message.type = (char *)messageObj["type"].as(); + + 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(); + message.username = (char *)messageObj["username"].as(); + message.bot_id = (char *)messageObj["bot_id"].as(); + message.type = (char *)messageObj["type"].as(); + + 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(); + profile.statusText = (char *)profileObj["status_text"].as(); + profile.statusEmoji = (char *)profileObj["status_emoji"].as(); + + profile.statusExpiration = profileObj["status_expiration"].as(); + + 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(); + } +} diff --git a/examples/slack/ArduinoSlack.h b/examples/slack/ArduinoSlack.h new file mode 100644 index 0000000..487db89 --- /dev/null +++ b/examples/slack/ArduinoSlack.h @@ -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 +#include +#include + +#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 diff --git a/examples/slack/ArduinoSlackCert.h b/examples/slack/ArduinoSlackCert.h new file mode 100644 index 0000000..9645bf2 --- /dev/null +++ b/examples/slack/ArduinoSlackCert.h @@ -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"; \ No newline at end of file diff --git a/examples/slack/myTest.ino.old b/examples/slack/myTest.ino.old new file mode 100644 index 0000000..7a1f690 --- /dev/null +++ b/examples/slack/myTest.ino.old @@ -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 +#include + +// ---------------------------- +// 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 +// 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; + } +} diff --git a/examples/slack/slack.ino b/examples/slack/slack.ino new file mode 100644 index 0000000..2518f42 --- /dev/null +++ b/examples/slack/slack.ino @@ -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 +#include +#include +#include + +#include +#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(); + } +} diff --git a/examples/weather/; b/examples/weather/; new file mode 100644 index 0000000..beb5ec6 --- /dev/null +++ b/examples/weather/; @@ -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 +#include +#include +#include + +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(); + } +} diff --git a/examples/weather/weather.ino b/examples/weather/weather.ino index 16da04f..780610c 100644 --- a/examples/weather/weather.ino +++ b/examples/weather/weather.ino @@ -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 +#include +#include +#include -/**********************/ -/* 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 "); - Serial.println(address); - if (set_address(address)) { - //set_address(address); - Serial.print(" D:"); - for (byte i=0; i> 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 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 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(); } diff --git a/examples/wifi_scan/wifi_scan.ino b/examples/wifi_scan/wifi_scan.ino index cc771e8..c5afdfd 100644 --- a/examples/wifi_scan/wifi_scan.ino +++ b/examples/wifi_scan/wifi_scan.ino @@ -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); diff --git a/lib/Apple2Idiot/Apple2Idiot.cpp b/lib/Apple2Idiot/Apple2Idiot.cpp index 1733bf2..68dccff 100644 --- a/lib/Apple2Idiot/Apple2Idiot.cpp +++ b/lib/Apple2Idiot/Apple2Idiot.cpp @@ -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> 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=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 diff --git a/notes.md b/notes.md index 90b530e..3f2f581 100644 --- a/notes.md +++ b/notes.md @@ -13,6 +13,10 @@ DONE: Add diode to +5V. Move ESP32 towards keyboard to accomodate USB Software reset of ESP32 +## Potential Trivial Features + ++ Gives each computer a unique ID (MAC address) ++ Prodos driver for NPT time. ## Thanks From ddc512fbbf1197c285a1356b7c531f4aef1104cd Mon Sep 17 00:00:00 2001 From: Nathanial Hendler Date: Sat, 11 Sep 2021 17:16:35 -0700 Subject: [PATCH 2/4] Beginnings of a slack example. --- examples/slack/credentials.h | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/slack/credentials.h diff --git a/examples/slack/credentials.h b/examples/slack/credentials.h new file mode 100644 index 0000000..744ca70 --- /dev/null +++ b/examples/slack/credentials.h @@ -0,0 +1,8 @@ +#ifndef CREDENTIALS_H +#define CREDENTIALS_H + +#define WIFI_SSID "GSO" +#define WIFI_PASSWORD "xerxes27" +#define SLACK_ACCESS_TOKEN "xoxp-52298054561-2192760530118-2480627120338-f945dcc4dd25c76c6b7faa7caa0a74c8" + +#endif From d0b08bb38040b99af8c2a7d10a61371654db0c8e Mon Sep 17 00:00:00 2001 From: Nathanial Hendler Date: Sat, 11 Sep 2021 17:38:02 -0700 Subject: [PATCH 3/4] README updated a bit --- README.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4e822e5..3fd0085 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,35 @@ # apple2idiot -A general purpose ESP32 IOT board for the Apple IIe +A general purpose ESP32 Wifi and Bluetooth board for the Apple II family of computers (with expansion slots). -Things are in the early stages of development, but it is working. The card contains an ESP32 which gives the Apple II access to wifi and bluetooth. It does not provide a TCP stack. Think of this as being more like making your Apple II an IOT device. +This card is essentially an ESP32 module and a dual-port ram chip. The Apple computer and the ESP communicate via the dual-port ram. That means that the ESP32 doesn't acutally have access to read/write any of the Apple computer's data or address busses. I think that's ok. In fact, I think this card is so simple, and stupid, that lots of fun little things can be done with it, but it's not meant to "get your Apple on the internet". + +As a user of the card, you write the software that runs on the ESP32 module, and the software that runs on the Apple computer. In the `examples/` folder are examples of how to do simple little things. Software on the apple just peeks/pokes commands and data to the ram chip, and the ESP responds however it's programmed to resppond. + +## Some of the example programs that have been developed so far + +* Send a message to Slack. +* Get current weather conditions for a city. +* Select Wifi AP. +* Dedicated rot13 string encoder. ## Status ### The Card This is actively being developed (as of September 2021). The rev 0.1 board doesn't work without -some bodge wires - -Rev 0.2 boards are going to be ordered sometime this month. +some bodge wires, and rev 0.2 boards are on their way from China. ### The Apple II Software None of the Apple //e code is up yet because I don't have a way to transfer it -from my 5.25 floppies to here. But all of this is underway. +from my 5.25 floppies to here. I hope to fix this soon. -### The Card Software +### The Card Software/Firmware -The ESP32 can be programmed using whatever you want. For example, you can use the Arduino IDE/C++ or you can use Lua, or Espressif's environment. Example Arduino programs are in the repo under examples. - -## Some of the example programs that have been developed so far - -* Get current weather conditions for a city. -* Select Wifi AP. -* Dedicated rot13 string encoder. +The ESP32 can be programmed using whatever you want. For example, you can use +the Arduino IDE/C++ or you can use Lua, or Espressif's environment. Example +Arduino programs are in the repo under examples. ## What could be done with an Apple2Idiot card? From b9abecf637673b4e2b9596277789527dd2001249 Mon Sep 17 00:00:00 2001 From: Nathanial Hendler Date: Sat, 11 Sep 2021 18:11:05 -0700 Subject: [PATCH 4/4] oops --- .gitignore | 1 + examples/slack/credentials.h | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 examples/slack/credentials.h diff --git a/.gitignore b/.gitignore index 8ddb554..462c361 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp .gitattributes +credentials.h diff --git a/examples/slack/credentials.h b/examples/slack/credentials.h deleted file mode 100644 index 744ca70..0000000 --- a/examples/slack/credentials.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CREDENTIALS_H -#define CREDENTIALS_H - -#define WIFI_SSID "GSO" -#define WIFI_PASSWORD "xerxes27" -#define SLACK_ACCESS_TOKEN "xoxp-52298054561-2192760530118-2480627120338-f945dcc4dd25c76c6b7faa7caa0a74c8" - -#endif