#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include "Mudbus.h"
#define LED_PIN 5
#define NUM_LEDS 8
#define RL1 14
#define RL2 15
#define EEPROM_IP_ADDRESS 0
#define EEPROM_GATEWAY 4
#define EEPROM_SUBNET 8
#define EEPROM_CONFIG_SET 12
#define EEPROM_MAC_ADDRESS 13
IPAddress ip, gateway, subnet;
uint8_t mac[6];
EthernetServer server(80);
Mudbus Mb;
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
const uint8_t numInputs = 10;
const uint8_t inputPins[numInputs] = {6, 7, 8, 9, 4, 3, 19, 18, 17, 16};
uint8_t tugas[numInputs] = {1, 1, 1, 1, 1, 1, 2, 4, 5, 9};
uint8_t antrian[numInputs] = {0};
uint8_t perintah = 0;
unsigned long previousMillis = 0;
void setup() {
Serial.begin(9600);
randomSeed(analogRead(0)); // Initialize random number generator
loadIPSettings();
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
Serial.print(F("Server is at "));
Serial.println(Ethernet.localIP());
pinMode(RL1, OUTPUT);
pinMode(RL2, OUTPUT);
strip.begin();
strip.show();
for (uint8_t i = 0; i < numInputs; i++) {
pinMode(inputPins[i], INPUT_PULLUP);
}
Mb.Run();
for (uint8_t i = 0; i < 10; i++) {
Mb.R[i] = tugas[i];
}
ledStartupSequence();
printSerialInstructions();
}
void loop() {
Mb.Run();
handleEthernetClient();
digitalWrite(RL1, Mb.C[10]);
digitalWrite(RL2, Mb.C[11]);
handleEthernetClient();
handleSerialCommands();
for (uint8_t i = 0; i < 10; i++) {
Mb.C[i] = digitalRead(inputPins[i]);
tugas[i] = Mb.R[i];
}
unsigned long currentMillis = millis();
updateAntrian();
perintah = getMaxTugas();
handleLEDControl(perintah, currentMillis);
}
void sendWebPage(EthernetClient& client) {
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/html"));
client.println();
client.println(F("<html><head><title>Arduino Network Config</title></head><body>"));
client.println(F("<h1>Arduino Network Configuration</h1>"));
// IP settings form
client.println(F("<h2>IP Settings</h2>"));
client.println(F("<form method='post' action='/setip'>"));
client.print(F("IP Address: <input type='text' name='ip' value='"));
client.print(Ethernet.localIP());
client.println(F("'><br>"));
client.print(F("Gateway: <input type='text' name='gateway' value='"));
client.print(Ethernet.gatewayIP());
client.println(F("'><br>"));
client.print(F("Subnet: <input type='text' name='subnet' value='"));
client.print(Ethernet.subnetMask());
client.println(F("'><br>"));
client.println(F("<input type='submit' value='Update IP Settings'>"));
client.println(F("</form>"));
// MAC address form
client.println(F("<h2>MAC Address</h2>"));
client.println(F("<form method='post' action='/setmac'>"));
client.print(F("MAC Address: <input type='text' name='mac' value='"));
for (uint8_t i = 0; i < 6; i++) {
client.print(mac[i], HEX);
if (i < 5) client.print(':');
}
client.println(F("'><br>"));
client.println(F("<input type='submit' value='Update MAC Address'>"));
client.println(F("</form>"));
// Generate random MAC button
client.println(F("<form method='post' action='/generatemac'>"));
client.println(F("<input type='submit' value='Generate Random MAC'>"));
client.println(F("</form>"));
client.println(F("</body></html>"));
}
void sendResponse(EthernetClient& client, const __FlashStringHelper* message) {
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/plain"));
client.println();
client.println(message);
}
void handleSerialCommands() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
if (command.startsWith("setip ")) {
handleSerialIPConfig(command);
} else if (command.startsWith("setmac ")) {
handleSerialMACConfig(command);
} else if (command == "genmac") {
handleSerialGenerateMAC();
} else if (command == "settings") {
printCurrentSettings();
} else if (command == "restart") {
Serial.println(F("Restarting device..."));
delay(1000);
softReset();
} else {
Serial.println(F("Invalid command. Type 'help' for instructions."));
}
}
}
void handleSerialIPConfig(const String& command) {
String params = command.substring(6);
int firstSpace = params.indexOf(' ');
int secondSpace = params.indexOf(' ', firstSpace + 1);
if (firstSpace == -1 || secondSpace == -1) {
Serial.println(F("Invalid IP configuration format."));
return;
}
String ipStr = params.substring(0, firstSpace);
String gatewayStr = params.substring(firstSpace + 1, secondSpace);
String subnetStr = params.substring(secondSpace + 1);
IPAddress newIP, newGateway, newSubnet;
if (newIP.fromString(ipStr) && newGateway.fromString(gatewayStr) && newSubnet.fromString(subnetStr)) {
saveIPSettings(newIP, newGateway, newSubnet);
Serial.println(F("IP settings updated. Device will restart in 5 seconds."));
delay(5000);
softReset();
} else {
Serial.println(F("Invalid IP settings."));
}
}
void handleSerialMACConfig(const String& command) {
String macStr = command.substring(7);
if (parseMACAddress(macStr)) {
saveMACSettings();
Serial.println(F("MAC address updated. Device will restart in 5 seconds."));
delay(5000);
softReset();
} else {
Serial.println(F("Invalid MAC address."));
}
}
void handleSerialGenerateMAC() {
generateRandomMAC();
saveMACSettings();
Serial.println(F("New MAC address generated and saved. Device will restart in 5 seconds."));
delay(5000);
softReset();
}
void printSerialInstructions() {
Serial.println(F("Available commands:"));
Serial.println(F("1. Set IP: setip <ip> <gateway> <subnet>"));
Serial.println(F("2. Set MAC: setmac <mac>"));
Serial.println(F("3. Generate random MAC: genmac"));
Serial.println(F("4. Print current settings: settings"));
Serial.println(F("5. Restart device: restart"));
}
void printCurrentSettings() {
Serial.println(F("Current settings:"));
Serial.print(F("IP: ")); Serial.println(Ethernet.localIP());
Serial.print(F("Gateway: ")); Serial.println(Ethernet.gatewayIP());
Serial.print(F("Subnet: ")); Serial.println(Ethernet.subnetMask());
Serial.print(F("MAC: "));
for (uint8_t i = 0; i < 6; i++) {
Serial.print(mac[i], HEX);
if (i < 5) Serial.print(':');
}
Serial.println();
}
void loadIPSettings() {
if (EEPROM.read(EEPROM_CONFIG_SET) == 1) {
for (uint8_t i = 0; i < 4; i++) {
ip[i] = EEPROM.read(EEPROM_IP_ADDRESS + i);
gateway[i] = EEPROM.read(EEPROM_GATEWAY + i);
subnet[i] = EEPROM.read(EEPROM_SUBNET + i);
}
for (uint8_t i = 0; i < 6; i++) {
mac[i] = EEPROM.read(EEPROM_MAC_ADDRESS + i);
}
Serial.println(F("Loaded IP and MAC settings from EEPROM"));
} else {
ip = IPAddress(192, 168, 1, 177);
gateway = IPAddress(192, 168, 1, 1);
subnet = IPAddress(255, 255, 255, 0);
generateRandomMAC();
Serial.println(F("Using default IP settings and generated MAC"));
}
Serial.print(F("IP: ")); Serial.println(ip);
Serial.print(F("Gateway: ")); Serial.println(gateway);
Serial.print(F("Subnet: ")); Serial.println(subnet);
Serial.print(F("MAC: "));
for (uint8_t i = 0; i < 6; i++) {
Serial.print(mac[i], HEX);
if (i < 5) Serial.print(':');
}
Serial.println();
}
void generateRandomMAC() {
mac[0] = 0xDE; // Locally administered address
for (int i = 1; i < 6; i++) {
mac[i] = random(0xFF);
}
}
void handleEthernetClient() {
EthernetClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
String httpRequest = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
httpRequest += c;
if (c == '\n' && currentLineIsBlank) {
if (httpRequest.indexOf("POST /setip") != -1) {
handleIPConfiguration(client, httpRequest);
} else if (httpRequest.indexOf("POST /setmac") != -1) {
handleMACConfiguration(client, httpRequest);
} else if (httpRequest.indexOf("POST /generatemac") != -1) {
handleGenerateMAC(client);
} else {
sendWebPage(client);
}
break;
}
if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
client.stop();
}
}
void handleIPConfiguration(EthernetClient& client, const String& httpRequest) {
IPAddress newIP, newGateway, newSubnet;
if (parseIPSettings(httpRequest, newIP, newGateway, newSubnet)) {
saveIPSettings(newIP, newGateway, newSubnet);
sendResponse(client, F("IP settings updated. Device will restart in 5 seconds."));
delay(5000);
softReset();
} else {
sendResponse(client, F("Invalid IP settings"));
}
}
void saveIPSettings(IPAddress newIP, IPAddress newGateway, IPAddress newSubnet) {
for (uint8_t i = 0; i < 4; i++) {
EEPROM.write(EEPROM_IP_ADDRESS + i, newIP[i]);
EEPROM.write(EEPROM_GATEWAY + i, newGateway[i]);
EEPROM.write(EEPROM_SUBNET + i, newSubnet[i]);
}
EEPROM.write(EEPROM_CONFIG_SET, 1);
Serial.println(F("IP settings saved to EEPROM"));
}
void handleMACConfiguration(EthernetClient& client, const String& httpRequest) {
String macStr = extractValueFromRequest(httpRequest, "mac");
if (parseMACAddress(macStr)) {
saveMACSettings();
sendResponse(client, F("MAC address updated. Device will restart in 5 seconds."));
delay(5000);
softReset();
} else {
sendResponse(client, F("Invalid MAC address"));
}
}
void saveMACSettings() {
for (uint8_t i = 0; i < 6; i++) {
EEPROM.write(EEPROM_MAC_ADDRESS + i, mac[i]);
}
Serial.println(F("MAC address saved to EEPROM"));
}
void handleGenerateMAC(EthernetClient& client) {
generateRandomMAC();
saveMACSettings();
sendResponse(client, F("New MAC address generated and saved. Device will restart in 5 seconds."));
delay(5000);
softReset();
}
bool parseIPSettings(const String& request, IPAddress& ip, IPAddress& gateway, IPAddress& subnet) {
String ipStr = extractValueFromRequest(request, "ip");
String gatewayStr = extractValueFromRequest(request, "gateway");
String subnetStr = extractValueFromRequest(request, "subnet");
return ip.fromString(ipStr) && gateway.fromString(gatewayStr) && subnet.fromString(subnetStr);
}
bool parseMACAddress(const String& macStr) {
uint8_t temp[6];
int values[6];
int i;
if (6 == sscanf(macStr.c_str(), "%x:%x:%x:%x:%x:%x", &values[0], &values[1], &values[2], &values[3], &values[4], &values[5])) {
for (i = 0; i < 6; ++i) {
temp[i] = (uint8_t) values[i];
}
memcpy(mac, temp, 6);
return true;
}
return false;
}
String extractValueFromRequest(const String& request, const char* key) {
int start = request.indexOf(key);
if (start == -1) return "";
start = request.indexOf('=', start) + 1;
int end = request.indexOf('&', start);
if (end == -1) end = request.indexOf(' ', start);
if (end == -1) return "";
return request.substring(start, end);
}
void softReset() {
asm volatile (" jmp 0");
}
void updateAntrian() {
for (uint8_t i = 0; i < numInputs; i++) {
antrian[i] = digitalRead(inputPins[i]) == LOW ? tugas[i] : 0;
}
}
uint8_t getMaxTugas() {
uint8_t maxTugas = 0;
for (uint8_t i = 0; i < numInputs; i++) {
if (antrian[i] > maxTugas) {
maxTugas = antrian[i];
}
}
return maxTugas;
}
void handleLEDControl(uint8_t perintah, unsigned long currentMillis) {
switch (perintah) {
case 0: ledsOff(); break;
case 1: blinkColor(strip.Color(0, 255, 0), 1000, currentMillis); break;
case 2: blinkColor(strip.Color(255, 0, 0), 700, currentMillis); break;
case 3: alternateBlink(strip.Color(0, 255, 0), 50, currentMillis); break;
case 4: blinkColor(strip.Color(255, 255, 0), 1000, currentMillis); break;
case 5: blinkColor(strip.Color(128, 0, 128), 700, currentMillis); break;
case 6: blinkColor(strip.Color(255, 255, 255), 500, currentMillis); break;
case 7: blinkColor(strip.Color(255, 20, 147), 300, currentMillis); break;
case 8: blinkColor(strip.Color(255, 0, 0), 300, currentMillis); break;
case 9: blinkColor(strip.Color(0, 0, 255), 200, currentMillis); break;
}
}
void ledsOff() {
strip.clear();
strip.show();
}
void blinkColor(uint32_t color, int interval, unsigned long currentMillis) {
static bool ledState = false;
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = !ledState;
strip.fill(ledState ? color : 0, 0, NUM_LEDS);
strip.show();
}
}
void alternateBlink(uint32_t color, int interval, unsigned long currentMillis) {
static uint8_t ledIndex = 0;
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
strip.clear();
strip.setPixelColor(ledIndex, color);
strip.show();
ledIndex = (ledIndex + 1) % NUM_LEDS;
}
}
void ledStartupSequence() {
uint32_t colors[] = {strip.Color(255, 0, 0), strip.Color(255, 255, 0), strip.Color(0, 255, 0)};
for (uint8_t i = 0; i < 3; i++) {
strip.fill(colors[i], 0, NUM_LEDS);
strip.show();
delay(1000);
strip.clear();
strip.show();
delay(900);
}
}