mirror of
https://github.com/equant/apple2idiot.git
synced 2024-06-16 12:09:14 +00:00
Context/App ISS/Weather switching example
This commit is contained in:
parent
9d3eb74bb4
commit
c8e475d90d
@ -37,8 +37,9 @@
|
||||
# PROGRAM IDS #
|
||||
################################################*/
|
||||
|
||||
#define APP_WEATHER 200 // Unimplemented
|
||||
#define APP_CHESS 201 // Unimplemented
|
||||
#define APP_WEATHER 200
|
||||
#define APP_CHESS 201
|
||||
#define APP_ISS 202
|
||||
|
||||
|
||||
/*################################################
|
||||
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
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 20
|
||||
#define COMMAND_SET_CITY 21
|
||||
#define COMMAND_FETCH_WEATHER 25
|
||||
|
||||
#include "credentials.h"
|
||||
|
||||
//const char* wifi_ssid = "HotelMcCoy-Guest";
|
||||
//const char* wifi_password = "travelforall";
|
||||
char wifi_ssid[] = WIFI_SSID; // your network SSID (name)
|
||||
char wifi_password[] = WIFI_PASSWORD; // your network password
|
||||
|
||||
/*******************/
|
||||
/* Weather Service */
|
||||
/*******************/
|
||||
|
||||
const String weather_service_api_key= "0ab97bbbea58592d7c9d64067a34d2d0";
|
||||
const String weather_url = "http://api.openweathermap.org/data/2.5/weather?";
|
||||
|
||||
String country_code = "US";
|
||||
String city_name = "Tucson";
|
||||
|
||||
/*******************/
|
||||
/* Misc */
|
||||
/*******************/
|
||||
|
||||
const long readLoopInterval = 100; // millis
|
||||
unsigned long lastReadLoopTime = 0;
|
||||
|
||||
byte lastAppleCommand = 0;
|
||||
|
||||
/*################################################
|
||||
# Setup #
|
||||
################################################*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("Starting 15_fixed_essid_weather-cc65.ino after a quick delay so that we have time to connect a serial monitor after restart and see what's going on");
|
||||
delay(3000);
|
||||
Serial.println("Starting 15_fixed_essid_weather-cc65.ino");
|
||||
|
||||
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() {
|
||||
|
||||
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_ACCESS_TOKEN;
|
||||
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 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:
|
||||
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;
|
||||
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;
|
||||
}
|
||||
lastReadLoopTime = millis();
|
||||
}
|
||||
}
|
13
examples/15_fixed_essid_weather-arduino/weather_commands.h
Normal file
13
examples/15_fixed_essid_weather-arduino/weather_commands.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef A2I_CHESS_COMMANDS_H
|
||||
#define A2I_CHESS_COMMANDS_H
|
||||
|
||||
/* Apple II <-> ESP Commands */
|
||||
#define COMMAND_SET_COUNTRY 20
|
||||
#define COMMAND_SET_CITY 21
|
||||
#define COMMAND_FETCH_WEATHER 25
|
||||
|
||||
/* Responses */
|
||||
//#define CHESS_INVALID_MOVE 123
|
||||
//#define CHESS_VALID_MOVE 124
|
||||
|
||||
#endif
|
@ -23,15 +23,15 @@
|
||||
1010 WS$ = CC$
|
||||
1020 WA = AA +1
|
||||
1030 GOSUB 10000
|
||||
1040 POKE AA,200 : REM SET COUNTRY
|
||||
1040 POKE AA,20 : REM SET COUNTRY
|
||||
1050 GOTO 100
|
||||
2000 INPUT "CITY: ";CITY$
|
||||
2010 WS$ = CITY$
|
||||
2020 WA = AA +1
|
||||
2030 GOSUB 10000
|
||||
2040 POKE AA,201 : REM SET CITY
|
||||
2040 POKE AA,21 : REM SET CITY
|
||||
2050 GOTO 100
|
||||
3000 POKE AA,205 : REM FETCH WEATHER
|
||||
3000 POKE AA,25 : REM FETCH WEATHER
|
||||
3010 GOTO 100
|
||||
4000 HOME
|
||||
4005 MAXSTR = 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
diskname='15_fixed_essid_weather-cc65.dsk'
|
||||
diskname='15_fixed_essid_weather-basic.dsk'
|
||||
|
||||
echo "-------------------------"
|
||||
echo "Files on disk image (before):"
|
||||
|
@ -15,8 +15,12 @@
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
|
||||
#define COMMAND_SET_COUNTRY 200
|
||||
#define COMMAND_SET_CITY 201
|
||||
#define COMMAND_FETCH_WEATHER 205
|
||||
#define APP_ID 200
|
||||
|
||||
#define COMMAND_SET_COUNTRY 20
|
||||
#define COMMAND_SET_CITY 21
|
||||
#define COMMAND_FETCH_WEATHER 25
|
||||
|
||||
#define DEFAULT_COUNTRY_CODE "US"
|
||||
|
||||
#endif
|
||||
|
@ -23,9 +23,12 @@ unsigned int address_offset = 0;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
||||
unsigned char key;
|
||||
clrscr();
|
||||
|
||||
write_byte(APPLE_COMMAND_ADDRESS, APP_ID);
|
||||
|
||||
while (key != ASCII_5) { // Last menu item should be Quit
|
||||
drawMenuBar();
|
||||
gotoxy(0,2);
|
||||
|
@ -7,8 +7,8 @@
|
||||
#include "menu.h"
|
||||
|
||||
#define MENU_LENGTH 5
|
||||
#define MENU_WORD_LENGTH 8
|
||||
unsigned char menuEntries[MENU_LENGTH][MENU_WORD_LENGTH] = {"Country", "City", "Fetch", "Display", "Quit"};
|
||||
#define MENU_WORD_LENGTH 9
|
||||
unsigned char menuEntries[MENU_LENGTH][MENU_WORD_LENGTH] = {"Country ", "City ", "Fetch ", "Display ", "Quit"};
|
||||
|
||||
void drawMenuBar() {
|
||||
static unsigned char i;
|
||||
|
Binary file not shown.
Binary file not shown.
164
examples/20-multiapp-arduino/20-multiapp-arduino.ino
Normal file
164
examples/20-multiapp-arduino/20-multiapp-arduino.ino
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Nathanial Hendler
|
||||
2021
|
||||
github.com/equant
|
||||
*/
|
||||
|
||||
// Load Wi-Fi library
|
||||
#include <WiFi.h>
|
||||
#include <Apple2Idiot.h>
|
||||
//#include <ArduinoJson.h>
|
||||
//#include <HTTPClient.h>
|
||||
#include "credentials.h"
|
||||
#include "a2i_weather.h"
|
||||
#include "a2i_iss.h"
|
||||
|
||||
#define AUTO_CONNECT_TO_WIFI 1
|
||||
#define AUTO_CONNECT_TIMEOUT 5
|
||||
|
||||
Apple2Idiot a2i = Apple2Idiot();
|
||||
//HTTPClient http;
|
||||
|
||||
/*################################################
|
||||
# Applications we're going to support #
|
||||
#
|
||||
# An Apple ][ running this card may want to run
|
||||
# several different "apps" that utilize the card.
|
||||
# These "apps" are classes (instantiated below)
|
||||
# which the main loop uses to handle/manage
|
||||
# communication with the Apple. For example, the
|
||||
# card may want to handle requests to support
|
||||
# programs on the Apple ][ such as a wifi
|
||||
# selector, a chess game, and a weather lookup
|
||||
# app.
|
||||
################################################*/
|
||||
|
||||
//Chess chess_app = Chess();
|
||||
Weather weather_app = Weather();
|
||||
Iss iss_app = Iss();
|
||||
|
||||
#define N_APPS 2
|
||||
//byte app_ids[N_APPS] = {APP_WEATHER, APP_ISS};
|
||||
byte app_ids[N_APPS] = {APP_ISS, APP_WEATHER};
|
||||
|
||||
/*******************/
|
||||
/* Variables */
|
||||
/*******************/
|
||||
|
||||
byte current_app_id;
|
||||
|
||||
const long mainLoopInterval = 100; // millis
|
||||
//const long mainLoopInterval = 10000; // millis
|
||||
unsigned long lastMainLoopTime = 0;
|
||||
byte lastAppleCommand = 0;
|
||||
|
||||
/*################################################
|
||||
# Setup #
|
||||
################################################*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
a2i.init();
|
||||
//chess_app.init(&a2i, &http);
|
||||
//weather_app.init(&a2i, &http);
|
||||
|
||||
#ifdef AUTO_CONNECT_TO_WIFI
|
||||
Serial.println("");
|
||||
Serial.print("Starting wifi, connecting to: ");
|
||||
Serial.println(WIFI_SSID);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
byte wifi_loop_count = 0;
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(600);
|
||||
wifi_loop_count++;
|
||||
Serial.print(".");
|
||||
if (wifi_loop_count > AUTO_CONNECT_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected successfully");
|
||||
Serial.print("Got IP: ");
|
||||
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
|
||||
} else {
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connection failed.");
|
||||
}
|
||||
#else
|
||||
// Set WiFi to station mode and disconnect from an AP if it was previously connected
|
||||
Serial.println("Wifi autoconnect not enabled. No wifi connection attempted.");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#endif
|
||||
|
||||
Serial.println("Setup done");
|
||||
current_app_id = app_ids[0];
|
||||
|
||||
}
|
||||
|
||||
/*################################################
|
||||
# Main #
|
||||
################################################*/
|
||||
|
||||
void loop() {
|
||||
|
||||
if ((millis() - lastMainLoopTime) > mainLoopInterval) {
|
||||
//Serial.print(".");
|
||||
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){
|
||||
lastAppleCommand = command_byte;
|
||||
byte result = 0;
|
||||
Serial.print("Handling command_byte: ");
|
||||
Serial.println(command_byte);
|
||||
|
||||
/* Do we need to switch app context? */
|
||||
for (int i=0; i<N_APPS; i++) {
|
||||
Serial.print("App loop: ");
|
||||
Serial.println(i);
|
||||
Serial.print("Checking ID: ");
|
||||
Serial.println(app_ids[i]);
|
||||
if (command_byte == app_ids[i]) {
|
||||
// We were sent an app id.
|
||||
Serial.println("We were sent an app id");
|
||||
if (current_app_id != command_byte) {
|
||||
// We are talking to a new app
|
||||
Serial.println("We are talking to a new app");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK);
|
||||
current_app_id = command_byte;
|
||||
}
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, EOT);
|
||||
lastMainLoopTime = millis();
|
||||
Serial.println("About to return");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here, we need to pass the command to app's class to be handled */
|
||||
|
||||
if (current_app_id == weather_app.appId) {
|
||||
Serial.println("Received a command for Weather()");
|
||||
weather_app.handleCommand(command_byte);
|
||||
Serial.println("...command for Weather() handled");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
}
|
||||
else if (current_app_id == iss_app.appId) {
|
||||
Serial.println("Received a command for ISS()");
|
||||
iss_app.handleCommand(command_byte);
|
||||
Serial.println("...command for ISS() handled");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
}
|
||||
else {
|
||||
Serial.println("Received a command for UNKNOWN()");
|
||||
}
|
||||
}
|
||||
lastMainLoopTime = millis();
|
||||
}
|
||||
}
|
7
examples/20-multiapp-arduino/README.md
Normal file
7
examples/20-multiapp-arduino/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Arduno sketch for Apple2 Internet Weather Client Examples
|
||||
|
||||
For now, this works with both the basic and and cc65 clients
|
||||
|
||||
`../15_fixed_essid_weather-basic`
|
||||
`../15_fixed_essid_weather-cc65`
|
||||
if arduino-cli compile --fqbn esp32:esp32:nodemcu-32s .; then arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32-poe-iso .; fi
|
281
examples/20-multiapp-arduino/a2i_chess.cpp
Normal file
281
examples/20-multiapp-arduino/a2i_chess.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "chess_commands.h"
|
||||
#include "a2i_chess.h"
|
||||
|
||||
|
||||
void Chess::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
//strcpy(game_string, "a2a3e7e5e2e4");
|
||||
}
|
||||
|
||||
byte Chess::handleCommand(byte command) {
|
||||
switch(command) {
|
||||
case CHESS_MAKE_MOVE: {
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("CHESS() MAKE_MOVE");
|
||||
String move_string;
|
||||
move_string = a2i->read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received move: ["+move_string+"]");
|
||||
byte result = makeMove(move_string);
|
||||
int address_counter = a2i->write_string_to_shared_ram(last_ai_move, SHARED_RAM_START_ADDRESS);
|
||||
getBoard();
|
||||
for (int i=0; i<9; i++) {
|
||||
address_counter = a2i->write_string_to_shared_ram(game_board[i], address_counter + 1);
|
||||
}
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, result);
|
||||
a2i->read_ram(11);
|
||||
break;
|
||||
}
|
||||
case CHESS_NEW_GAME: {
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("CHESS_NEW_GAME");
|
||||
strcpy(game_string, "");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Chess::makeMove(String move_string) {
|
||||
/* Apple says MAKE_MOVE and sends "a2a3"
|
||||
*
|
||||
* The basic flow...
|
||||
*
|
||||
* validateMove() We check that it's valid.
|
||||
* If it is we accept the move and add it to game_string
|
||||
* getGameStatus() Then we check the status and return (did someone win or lose?)
|
||||
* getAIMove() Then we get the AI move.
|
||||
* Then we check the status and return (did someone win or lose?)
|
||||
*/
|
||||
if (validateMove(move_string) == CHESS_VALID_MOVE) {
|
||||
strcat(game_string, move_string.c_str());
|
||||
} else {
|
||||
return CHESS_INVALID_MOVE;
|
||||
}
|
||||
char* game_status;
|
||||
//b = getGameStatus(game_string);
|
||||
game_status = getGameStatus(game_string);
|
||||
Serial.print("after player move game_status:"); Serial.println(game_status);
|
||||
|
||||
if (strcmp(game_status, "in_progress") == 0) {
|
||||
//char* ai_move;
|
||||
//ai_move = getAIMove();
|
||||
//strcat(game_string, ai_move);
|
||||
//last_ai_move = getAIMove();
|
||||
strcpy(last_ai_move, getAIMove());
|
||||
strcat(game_string, last_ai_move);
|
||||
game_status = getGameStatus(game_string);
|
||||
Serial.print("after AI move game_status:"); Serial.println(game_status);
|
||||
if (strcmp(game_status, "in_progress") == 0) { return STATUS_IN_PROGRESS; }
|
||||
else if (strcmp(game_status, "black_won") == 0) { return STATUS_BLACK_WON; }
|
||||
else if (strcmp(game_status, "white_won") == 0) { return STATUS_WHITE_WON; }
|
||||
else if (strcmp(game_status, "white_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "black_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "stalemate") == 0) { return STATUS_STALEMATE; }
|
||||
else if (strcmp(game_status, "insufficient_material") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "fifty_rule_move") == 0) { return STATUS_FIFTY_RULE_MOVE; }
|
||||
else if (strcmp(game_status, "threefold_repitition") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "unknown") == 0) { return STATUS_UNKNOWN; } else { return STATUS_ERROR; }
|
||||
}
|
||||
else if (strcmp(game_status, "black_won") == 0) { return STATUS_BLACK_WON; }
|
||||
else if (strcmp(game_status, "white_won") == 0) { return STATUS_WHITE_WON; }
|
||||
else if (strcmp(game_status, "white_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "black_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "stalemate") == 0) { return STATUS_STALEMATE; }
|
||||
else if (strcmp(game_status, "insufficient_material") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "fifty_rule_move") == 0) { return STATUS_FIFTY_RULE_MOVE; }
|
||||
else if (strcmp(game_status, "threefold_repitition") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "unknown") == 0) { return STATUS_UNKNOWN; } else { return STATUS_ERROR; }
|
||||
}
|
||||
|
||||
char* Chess::getGameStatus(char* game_string) {
|
||||
Serial.print("getGameStatus() "); Serial.println(game_status);
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/status/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F(" deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return "error";
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println();
|
||||
Serial.println("----------------------");
|
||||
//return doc["gameStatus"];
|
||||
return (char *)doc["gameStatus"].as<char *>();
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
return "error";
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
|
||||
return "error";
|
||||
}
|
||||
|
||||
char* Chess::getAIMove() {
|
||||
Serial.print("getAIMove() "); Serial.println(game_status);
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/next_best/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F(" deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return "jsonerror";
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println();
|
||||
Serial.println("----------------------");
|
||||
//return doc["gameStatus"];
|
||||
return (char *)doc["bestNext"].as<char *>();
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
return "geterror";
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
|
||||
return "unknownerror";
|
||||
}
|
||||
|
||||
byte Chess::validateMove(String move_string) {
|
||||
Serial.print("validateMove() "); Serial.println(move_string);
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/valid_move/%s%s", api_entry_point, game_string, move_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return ERR;
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println();
|
||||
Serial.println("----------------------");
|
||||
bool validMove = doc["validMove"];
|
||||
if (validMove) {
|
||||
// good move
|
||||
Serial.println(" Valid move!");
|
||||
return CHESS_VALID_MOVE;
|
||||
} else {
|
||||
Serial.println(" Invalid move!");
|
||||
return CHESS_INVALID_MOVE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
return ERR;
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
return ERR;
|
||||
}
|
||||
|
||||
void Chess::removeSubstr (char *string, char *sub) {
|
||||
char *match = string;
|
||||
int len = strlen(sub);
|
||||
while ((match = strstr(match, sub))) {
|
||||
*match = '\0';
|
||||
strcat(string, match+len);
|
||||
match++;
|
||||
}
|
||||
}
|
||||
|
||||
void Chess::getBoard() {
|
||||
Serial.println("getBoard() ");
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/board_string/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
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();
|
||||
//Serial.println("----------------------");
|
||||
//Serial.println(" Break up the board...");
|
||||
//Serial.print(" BOARD:"); Serial.println((char *)doc["board"].as<char *>());
|
||||
char* pch = NULL;
|
||||
pch = strtok((char *)doc["board"].as<char *>(), "\n");
|
||||
//Serial.print(" pch:");Serial.println(pch);
|
||||
int row_count = 0;
|
||||
while (pch != NULL) {
|
||||
char board_line[30];
|
||||
strcpy(board_line, pch);
|
||||
removeSubstr(board_line, "[37m");
|
||||
removeSubstr(board_line, "[0m");
|
||||
removeSubstr(board_line, "\n");
|
||||
removeSubstr(board_line, "\e"); // remove escape (ASCII 27)
|
||||
removeSubstr(board_line, "\e"); // remove escape (ASCII 27)
|
||||
//Serial.print("(");Serial.print(row_count);Serial.print(")");
|
||||
//Serial.print(board_line); Serial.println("|");
|
||||
strcpy(game_board[row_count], board_line); // valid
|
||||
pch = strtok(NULL, "\n");
|
||||
row_count++;
|
||||
}
|
||||
Serial.println();
|
||||
for (int i=0; i<9; i++) {
|
||||
Serial.print("[");Serial.print(game_board[i]);Serial.println("]");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
}
|
66
examples/20-multiapp-arduino/a2i_chess.h
Normal file
66
examples/20-multiapp-arduino/a2i_chess.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef A2I_CHESS_H
|
||||
#define A2I_CHESS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <A2I_commands.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "chess_commands.h"
|
||||
|
||||
|
||||
#define MAX_GAME_SIZE 110 * 4 // This is probably not enough, but it's fine for development.
|
||||
// https://chess.stackexchange.com/questions/2506/what-is-the-average-length-of-a-game-of-chess
|
||||
// times four because one move is "e7e5"
|
||||
|
||||
class Chess {
|
||||
|
||||
public:
|
||||
byte appId = APP_CHESS; // This is "registered" with A2I_commands.h which is part of Apple2Idiot.h
|
||||
// This id is sent from the Apple to the ESP to tell the esp what app
|
||||
// is currently active. The main loop of the ESP sketch then knows to use
|
||||
// this class to respond to incoming commands from the Apple.
|
||||
|
||||
|
||||
char game_string[MAX_GAME_SIZE]; // This is probably not enough, but it's fine for development.
|
||||
|
||||
char game_status[25];
|
||||
char last_player_move[5]; // "a2a4"
|
||||
char last_ai_move[5]; // "8g76"
|
||||
|
||||
//char game_board[9][20];
|
||||
char game_board[9][22] = {
|
||||
"8 r n b q k b n r",
|
||||
"7 p p p p p p p p",
|
||||
"6 . . . . . . . .",
|
||||
"5 . . . . . . . .",
|
||||
"4 . . . . . . . .",
|
||||
"3 . . . . . . . .",
|
||||
"2 P P P P P P P P",
|
||||
"1 R N B Q K B N R",
|
||||
" a b c d e f g h"
|
||||
};
|
||||
|
||||
void init(Apple2Idiot *a2ip, HTTPClient *httpp);
|
||||
char* getGameStatus(char* game_status);
|
||||
byte makeMove(String move_string);
|
||||
byte handleCommand(byte command);
|
||||
byte validateMove(String move_string);
|
||||
char* getAIMove();
|
||||
void getBoard();
|
||||
|
||||
private:
|
||||
|
||||
Apple2Idiot *a2i;
|
||||
HTTPClient *http;
|
||||
|
||||
void removeSubstr (char *string, char *sub);
|
||||
const char api_entry_point[32] = "http://chess-api.herokuapp.com";
|
||||
/* Remember, flexible array won't work
|
||||
* in a class, so don't try to do this...
|
||||
* const char foo[] = "hello world";
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
92
examples/20-multiapp-arduino/a2i_iss.cpp
Normal file
92
examples/20-multiapp-arduino/a2i_iss.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "iss_commands.h"
|
||||
#include "a2i_iss.h"
|
||||
|
||||
|
||||
void Iss::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
Serial.println("ISS()::init()");
|
||||
}
|
||||
|
||||
byte Iss::handleCommand(byte command) {
|
||||
Serial.println("ISS() handleCommand");
|
||||
switch(command) {
|
||||
case COMMAND_GET_ISS: {
|
||||
Serial.println("ISS() COMMAND_GET_ISS");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("ISS() before fetch_iss()");
|
||||
return fetch_iss();
|
||||
}
|
||||
default: {
|
||||
Serial.print("ISS() COMMAND_NOT_FOUND: ");
|
||||
Serial.println(command);
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Iss::fetch_iss() {
|
||||
|
||||
byte result = 0;
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s", api_entry_point);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
|
||||
int httpCode = http.GET(); //Make the request
|
||||
Serial.print(" "); Serial.println("After GET()");
|
||||
delay(10);
|
||||
Serial.print(" httpCode:"); Serial.println(httpCode);
|
||||
|
||||
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["iss_position"]["latitude"] = true;
|
||||
filter["iss_position"]["longitude"] = true;
|
||||
filter["timestamp"] = true;
|
||||
filter["message"]["humidity"] = 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["iss_position"], Serial);
|
||||
Serial.println("----------------------");
|
||||
String latitude = doc["iss_position"]["latitude"];
|
||||
String longitude = doc["iss_position"]["longitude"];
|
||||
String timestamp = doc["timestamp"];
|
||||
String message = doc["messasge"];
|
||||
int address_counter = a2i.write_string_to_shared_ram(latitude, SHARED_RAM_START_ADDRESS);
|
||||
address_counter = a2i.write_string_to_shared_ram(longitude, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(timestamp, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(message, address_counter + 1);
|
||||
}
|
||||
result = ACK;
|
||||
}
|
||||
else {
|
||||
Serial.println("Error on HTTP request");
|
||||
result = ERR;
|
||||
}
|
||||
|
||||
http.end(); //Free the resources
|
||||
return result;
|
||||
}
|
||||
|
43
examples/20-multiapp-arduino/a2i_iss.h
Normal file
43
examples/20-multiapp-arduino/a2i_iss.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef A2I_ISS_H
|
||||
#define A2I_ISS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <A2I_commands.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "iss_commands.h"
|
||||
|
||||
class Iss {
|
||||
|
||||
public:
|
||||
// This is "registered" with A2I_commands.h which is part of Apple2Idiot.h This
|
||||
// id is sent from the Apple to the ESP to tell the esp what app is currently
|
||||
// active. The main loop of the ESP sketch then knows to use this class to
|
||||
// respond to incoming commands from the Apple.
|
||||
byte appId = APP_ISS;
|
||||
|
||||
void init(Apple2Idiot *a2ip, HTTPClient *httpp);
|
||||
//char* getGameStatus(char* game_status);
|
||||
//byte makeMove(String move_string);
|
||||
byte handleCommand(byte command);
|
||||
byte fetch_iss();
|
||||
//byte validateMove(String move_string);
|
||||
//char* getAIMove();
|
||||
//void getBoard();
|
||||
|
||||
private:
|
||||
|
||||
Apple2Idiot *a2i;
|
||||
HTTPClient *http;
|
||||
|
||||
void removeSubstr (char *string, char *sub);
|
||||
const char api_entry_point[49] = "http://api.open-notify.org/iss-now.json";
|
||||
/* Remember, flexible array won't work
|
||||
* in a class, so don't try to do this...
|
||||
* const char foo[] = "hello world";
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
119
examples/20-multiapp-arduino/a2i_weather.cpp
Normal file
119
examples/20-multiapp-arduino/a2i_weather.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "weather_commands.h"
|
||||
#include "a2i_weather.h"
|
||||
#include "credentials.h"
|
||||
|
||||
|
||||
void Weather::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
Serial.println("WEATHER()::init()");
|
||||
}
|
||||
|
||||
byte Weather::handleCommand(byte command) {
|
||||
Serial.println("WEATHER() handleCommand");
|
||||
switch(command) {
|
||||
case COMMAND_FETCH_WEATHER: {
|
||||
Serial.println("WEATHER() COMMAND_FETCH_WEATHER");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("WEATHER() before fetch_weather()");
|
||||
return fetch_weather();
|
||||
}
|
||||
case COMMAND_SET_COUNTRY: {
|
||||
Serial.println("WEATHER() 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 CountryCode: ["+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
|
||||
return ACK;
|
||||
//break;
|
||||
}
|
||||
case COMMAND_SET_CITY: {
|
||||
//a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.print("WEATHER() 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 CityName: ["+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
|
||||
return ACK;
|
||||
}
|
||||
default: {
|
||||
Serial.print("WEATHER() COMMAND_NOT_FOUND: ");
|
||||
Serial.println(command);
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Weather::fetch_weather() {
|
||||
|
||||
byte result = 0;
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%sq=%s,%s&APPID=%s", api_entry_point, city_name, country_code, WEATHER_ACCESS_TOKEN);
|
||||
//sprintf(api_request, "http://api.openweathermap.org/data/2.5/weather?q=TUCSON,US&APPID=0ab97bbbea58592d7c9d64067a34d2d0");
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
|
||||
int httpCode = http.GET(); //Make the request
|
||||
Serial.print(" "); Serial.println("After GET()");
|
||||
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;
|
||||
}
|
||||
|
47
examples/20-multiapp-arduino/a2i_weather.h
Normal file
47
examples/20-multiapp-arduino/a2i_weather.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef A2I_CHESS_H
|
||||
#define A2I_CHESS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <A2I_commands.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "weather_commands.h"
|
||||
#include "credentials.h"
|
||||
|
||||
class Weather {
|
||||
|
||||
public:
|
||||
// This is "registered" with A2I_commands.h which is part of Apple2Idiot.h This
|
||||
// id is sent from the Apple to the ESP to tell the esp what app is currently
|
||||
// active. The main loop of the ESP sketch then knows to use this class to
|
||||
// respond to incoming commands from the Apple.
|
||||
byte appId = APP_WEATHER;
|
||||
|
||||
String country_code = "US";
|
||||
String city_name = "Tucson";
|
||||
|
||||
void init(Apple2Idiot *a2ip, HTTPClient *httpp);
|
||||
//char* getGameStatus(char* game_status);
|
||||
//byte makeMove(String move_string);
|
||||
byte handleCommand(byte command);
|
||||
byte fetch_weather();
|
||||
//byte validateMove(String move_string);
|
||||
//char* getAIMove();
|
||||
//void getBoard();
|
||||
|
||||
private:
|
||||
|
||||
Apple2Idiot *a2i;
|
||||
HTTPClient *http;
|
||||
|
||||
void removeSubstr (char *string, char *sub);
|
||||
const char api_entry_point[49] = "http://api.openweathermap.org/data/2.5/weather?";
|
||||
/* Remember, flexible array won't work
|
||||
* in a class, so don't try to do this...
|
||||
* const char foo[] = "hello world";
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
38
examples/20-multiapp-arduino/chess_commands.h
Normal file
38
examples/20-multiapp-arduino/chess_commands.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef A2I_CHESS_COMMANDS_H
|
||||
#define A2I_CHESS_COMMANDS_H
|
||||
|
||||
/* Apple II <-> ESP Commands */
|
||||
#define CHESS_NEW_GAME 10
|
||||
#define CHESS_GET_AI_MOVE 20
|
||||
#define CHESS_GET_GAME_STATUS 22
|
||||
#define CHESS_GET_BOARD 23
|
||||
#define CHESS_MAKE_MOVE 21
|
||||
|
||||
/* Responses */
|
||||
#define CHESS_INVALID_MOVE 123
|
||||
#define CHESS_VALID_MOVE 124
|
||||
|
||||
/*
|
||||
* Responses from API...
|
||||
* "in_progress"
|
||||
* "black_won"
|
||||
* "white_won"
|
||||
* "white_won_resign"
|
||||
* "black_won_resign"
|
||||
* "stalemate"
|
||||
* "insufficient_material"
|
||||
* "fifty_rule_move"
|
||||
* "threefold_repitition"
|
||||
* "unknown"
|
||||
*/
|
||||
|
||||
#define STATUS_IN_PROGRESS 200
|
||||
#define STATUS_BLACK_WON 201
|
||||
#define STATUS_WHITE_WON 202
|
||||
#define STATUS_STALEMATE 205
|
||||
#define STATUS_FIFTY_RULE_MOVE 207
|
||||
#define STATUS_UNKNOWN 209
|
||||
#define STATUS_UNHANDLED 210
|
||||
#define STATUS_ERROR 211
|
||||
|
||||
#endif
|
12
examples/20-multiapp-arduino/credentials.h.sample
Normal file
12
examples/20-multiapp-arduino/credentials.h.sample
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef CREDENTIALS_H
|
||||
#define CREDENTIALS_H
|
||||
|
||||
#include "credentials.h"
|
||||
// copy credentials.h.sample to credentials.h and edit
|
||||
// so it contains your passwords and tokens.
|
||||
|
||||
#define WIFI_SSID "XXXXXXXXXXXXXXX";
|
||||
#define WIFI_PASSWORD "XXXXXXXXXXXXXXX";
|
||||
#define WEATHER_ACCESS_TOKEN "XXXXXXXXXXXXXXX"
|
||||
|
||||
#endif
|
9
examples/20-multiapp-arduino/iss_commands.h
Normal file
9
examples/20-multiapp-arduino/iss_commands.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef A2I_ISS_COMMANDS_H
|
||||
#define A2I_ISS_COMMANDS_H
|
||||
|
||||
/* Apple II <-> ESP Commands */
|
||||
#define COMMAND_GET_ISS 20
|
||||
|
||||
/* Responses */
|
||||
|
||||
#endif
|
13
examples/20-multiapp-arduino/weather_commands.h
Normal file
13
examples/20-multiapp-arduino/weather_commands.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef A2I_WEATHER_COMMANDS_H
|
||||
#define A2I_WEATHER_COMMANDS_H
|
||||
|
||||
/* Apple II <-> ESP Commands */
|
||||
#define COMMAND_SET_COUNTRY 20
|
||||
#define COMMAND_SET_CITY 21
|
||||
#define COMMAND_FETCH_WEATHER 25
|
||||
|
||||
/* Responses */
|
||||
//#define CHESS_INVALID_MOVE 123
|
||||
//#define CHESS_VALID_MOVE 124
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user