Analisis Kinerja Model Rancangan Sistem Home_Automation Berbasis Internet Protocol Terhadap Penggunaan Http Persistent dan Non-Persistent

(1)

LAMPIRAN 1

KODE PROGRAM KONTROLER

Fugue.ino / * *

* Fugue – Sebuah pr ogr am Ar dui no unt uk Home Aut omat i on. *

* @package Nugr aha

* @Aut hor Wahyu Nugr aha <nugr aha. c. wahyu@gmai l . com> * /

#i nc l ude " Fugue. h" names pac e Mai n {

us i ng Nugr aha: : Foundat i on: : Bas eCont r ol l er ;

c l as s Cont r ol l er : publ i c v i r t ual Bas eCont r ol l er {

publ i c:

v oi d s et up( ) {

Debug: : i s DebugMode = t r ue;

i f( ! env : : wi f i : : obt ai nI pAddr es s Aut omat i c al l y ) {

Wi Fi .c onf i g( env : : wi f i : : i p, env : : wi f i : : gat eway , env : : wi f i : : s ubnet , env : : wi f i : : dns 1, env : : wi f i : : dns 2) ;

}

boar d- >i ni t i al i z e( ) ; boar d- >aut omat e( ) ; }

v oi d l oop( ) {

Sc hedul er: : handl eEv ent s ( ) ; }

} ; }

#i nc l ude " boot s t r ap/ boot s t r ap. hpp"

App/Boards/WemosD1.hpp

namespace App { namespace Boards { usingnamespace App::Devices;

using Nugraha::Foundation::Board;

using App::Gateways::WebServer::Server; usingnamespace App::Gateways::HttpClients;


(2)

classWemosD1 : publicvirtual Board { protected:

void gateways() {

// this->attachGateway(new Server());

this->attachGateway(new PersistentHttp(std::map<String, String>({ { "host" , env::httpClient::host },

{ "mode" , env::httpClient::mode },

{ "publishKey" , env::httpClient::publishKey }, { "subscribeKey" , env::httpClient::subscribeKey }, { "signature" , env::httpClient::signature }, { "channelName" , env::httpClient::channelName }, { "callback" , env::httpClient::callback } })));

}

void devices() {

this->attachDevice(new Lampu(D2, NULL)); this->attachDevice(new Lampu(D3, NULL)); this->attachDevice(new Lampu(D4, NULL)); this->attachDevice(new Lampu(D5, NULL));

this->attachDevice(new AirConditioner(D6, NULL)); this->attachDevice(new LED(BUILTIN_LED, NULL)); }

void sensors() {

} }; }}

app/Devices/AirConditioner.hpp

namespace App { namespace Devices { using Nugraha::Sensors::Sensor; using Nugraha::Devices::Device;

using Nugraha::Devices::Drivers::AirConditionerDriver; classAirConditioner : publicvirtual Device

{ public:

AirConditioner(int pin, Sensor* sensor=NULL) : Device(pin, sensor) {}

void initialize() {

pinMode(this->pin, OUTPUT);

setDriver(new AirConditionerDriver()); }


(3)

{ } }; }}

app/Devices/Lampu.hpp

namespace App { namespace Devices { using Nugraha::Sensors::Sensor; using Nugraha::Devices::Device; classLampu : publicvirtual Device {

public:

Lampu(int pin, Sensor* sensor=NULL) : Device(pin, sensor) {}

void initialize() {

pinMode(this->pin, OUTPUT); }

void behavior() {

} }; }}

app/Gateways/HttpClients/NonPersistentHttp.hpp

namespace App { namespace Gateways { namespace HttpClients { using Nugraha::Gateways::Esp8266::WifiHttpClient;

classNonPersistentHttp : publicvirtual WifiHttpClient {

public:

NonPersistentHttp(std::map<String, String> setting):WifiHttpClient(setting) {} void service()

{

Debug::println("Memulai service koneksi HTTP Non-persistent..."); interval = 0;

http.setReuse(false);

Scheduler::every(interval, [=]() { updateMessage();

httpGet(generateUri(), [=]() {

board->executeUserCommand(response); });

}); } };


(4)

}}}

app/Gateways/HttpClients/PersistentHttp.hpp

namespace App { namespace Gateways { namespace HttpClients { using Nugraha::Gateways::Esp8266::WifiHttpClient;

classPersistentHttp : publicvirtual WifiHttpClient {

public:

PersistentHttp(std::map<String, String> setting) : WifiHttpClient(setting) {} void service()

{

Debug::println("Memulai service koneksi HTTP Persistent..."); interval = 0;

http.setReuse(true);

Scheduler::every(interval, [=]() { updateMessage();

httpGet(generateUri(), [=]() {

board->executeUserCommand(response); });

}); } }; }}}

config/env.hpp namespace env { namespace wifi {

String ssid = "Fugue2";

String password = "fugue123";

bool obtainIpAddressAutomatically = false; IPAddress ip(192, 168, 137, 69); IPAddress subnet(255, 255, 255, 0); IPAddress gateway(192, 168, 137, 1); IPAddress dns1(8, 8, 8, 8);

IPAddress dns2(8, 8, 4, 4); }

namespace httpClient {

String host = "www.wahyunugraha.com"; String mode = "publish";

String publishKey = "pub-w-3e5de365-5d57-48c7-a317-366ef2846eb4"; String subscribeKey = "sub-n-cca59b64-d972-11e5-bdd5-02ee2ddab7fe"; String signature = "0";

String channelName = "rumah1"; String callback = "0";


(5)

namespace server {

ESP8266WebServer* server = new ESP8266WebServer(80); }

}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Devices/Drivers/AirConditionerDriver.hpp namespace Nugraha { namespace Devices { namespace Drivers {

using Nugraha::Support::Facades::Scheduler::Scheduler; classAirConditionerDriver: publicvirtual Driver {

protected: public:

bool turnOn(int pin) {

digitalWrite(pin, HIGH); Scheduler::after(50, [=]() { digitalWrite(pin, LOW); });

returntrue; }

bool turnOff(int pin) {

digitalWrite(pin, HIGH); Scheduler::after(50, [=]() { digitalWrite(pin, LOW); }); returntrue; } }; }}} vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Devices/Drivers/SinkModeDriver.hpp namespace Nugraha { namespace Devices { namespace Drivers {

classSinkModeDriver : publicvirtual Driver {

protected: public:

bool turnOn(int pin) {

digitalWrite(pin, LOW); returntrue;

}

bool turnOff(int pin) {

digitalWrite(pin, HIGH); returntrue;

} };


(6)

}}}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Devices/Device.hpp namespace Nugraha { namespace Devices {

using Nugraha::Traits::HasId; using Nugraha::Traits::HasLogger; using Nugraha::Support::Facades::Debug;

using Nugraha::Contracts::Sensors::SensorContract; using Nugraha::Contracts::Devices::DriverContract; using Nugraha::Contracts::Devices::DeviceContract; using Nugraha::Contracts::Foundation::LoggerContract;

classDevice : publicvirtual DeviceContract, public HasLogger, public HasId {

protected: int pin = -1; bool isOn = false;

SensorContract* sensor; DriverContract* driver; unsignedlong previousMillis = 0; static DriverContract* defaultDriver; public:

Device(int pin, SensorContract* sensor) {

this->pin = pin; this->sensor = sensor;

this->driver = Device::defaultDriver; }

virtual ~Device() {} void toggle()

{

if (this->isOn==false) { this->turnOn();

} else {

this->turnOff(); } }

void turnOn() {

if(this->pin != -1) {

if(driver->turnOn(this->pin)) { this->isOn = true;

logger->addNotification(1, String(this->pin)); }

} }

void turnOff() {

if(this->pin != -1) {

if(driver->turnOff(this->pin)) { this->isOn = false;

logger->addNotification(0, String(this->pin)); }


(7)

}

int getPin() {

returnthis->pin; }

void setSensor(SensorContract* sensor) {

this->sensor = sensor; }

void setDriver(DriverContract* driver) {

this->driver = driver; }

int getId() override {HasId::getId();}

void setLogger(LoggerContract* logger) override {HasLogger::setLogger(logger);} LoggerContract* getLogger() override {HasLogger::getLogger();}

}; }}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Foundation/Application.hpp namespace Nugraha { namespace Foundation {

using Nugraha::Contracts::Foundation::BoardContract; classApplication

{ public:

BaseController* controller;

int serialBaudRate;

bool beginSerial;

Application(BaseController* controller, BoardContract* board, int

serialBaudRate, bool beginSerial) {

this->controller = controller; this->controller->board = board;

this->serialBaudRate = serialBaudRate; this->beginSerial = beginSerial;

}

virtual ~Application() {} virtualvoid setup()

{

this->controller->setup(); }

virtualvoid loop() {

this->controller->loop(); }


(8)

}; }}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Foundation/BaseController.hpp namespace Nugraha { namespace Foundation {

using Nugraha::Contracts::Foundation::BoardContract; classBaseController

{ public:

BoardContract* board; virtual ~BaseController() {} virtualvoid setup()=0;

virtualvoid loop()=0; };

}}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Foundation/Board.hpp namespace Nugraha { namespace Foundation {

using Nugraha::Traits::HasLogger; using Nugraha::Collections::Vector;

using Nugraha::Contracts::Devices::DeviceContract; using Nugraha::Contracts::Sensors::SensorContract; using Nugraha::Contracts::Gateways::GatewayContract; using Nugraha::Contracts::Foundation::BoardContract; using Nugraha::Contracts::Foundation::LoggerContract; using Nugraha::Contracts::Collections::CollectionContract; classBoard : publicvirtual BoardContract, public HasLogger {

protected:

CollectionContract<DeviceContract*>* devicesCollection; CollectionContract<SensorContract*>* sensorsCollection; CollectionContract<GatewayContract*>* gatewaysCollection; DeviceContract* Default = NULL;

voidinitializeAll() {

/** Inisialisasi setiap Gateway. */

for(int i=0; i<gatewaysCollection->count(); i++) { if(gatewaysCollection->getMemberAt(i) != NULL) {

gatewaysCollection->getMemberAt(i)->initialize(); }

}

/** Inisialisasi setiap Device. */

for(int i=0; i<devicesCollection->count(); i++) { if(devicesCollection->getMemberAt(i) != NULL) {

devicesCollection->getMemberAt(i)->initialize(); }


(9)

} } public: Board() {

devicesCollection = new Vector<DeviceContract*>(); sensorsCollection = new Vector<SensorContract*>(); gatewaysCollection = new Vector<GatewayContract*>(); setLogger(new Logger());

}

void initialize() { sensors(); devices(); gateways(); initializeAll(); }

void automate() {

/** Jalankan behavior setiap Device. */

for(int i=0; i<devicesCollection->count(); i++) { if(devicesCollection->getMemberAt(i) != NULL) {

devicesCollection->getMemberAt(i)->behavior();

devicesCollection->getMemberAt(i)->setLogger(logger); }

}

/** Jalankan service setiap Gateway. */

for(int i=0; i<gatewaysCollection->count(); i++) { if(gatewaysCollection->getMemberAt(i) != NULL) {

gatewaysCollection->getMemberAt(i)->service();

gatewaysCollection->getMemberAt(i)->setLogger(logger); gatewaysCollection->getMemberAt(i)->setBoard(this); }

} }

void attachDevice(DeviceContract* device) {

devicesCollection->add(device); }

void attachSensor(SensorContract* sensor) {

sensorsCollection->add(sensor); }

void attachGateway(GatewayContract* gateway) {

gatewaysCollection->add(gateway); }

void executeUserCommand(String userCommands) {

DeviceContract* device;


(10)

JsonObject& root = jsonBuffer.parseObject(userCommands); if (!root.success()) {

Serial.println("parseObject() failed"); return;

}

for(int i=0; i<root["commands"].size(); i++) {

int pin = root["commands"][i]["pin"];

String action = root["commands"][i]["action"]; if(action=="turnOn") {

if((device=getDeviceByPin(pin)) != NULL) { device->turnOn(); }

} elseif(action=="turnOff") { if((device=getDeviceByPin(pin)) != NULL) { device->turnOff(); }

} elseif(action=="toggle") { if((device=getDeviceByPin(pin)) != NULL) { device->toggle(); }

} } }

DeviceContract* getDeviceByPin(int pin) {

DeviceContract* device;

for(int i=0; i<devicesCollection->count(); i++) {

device = devicesCollection->getMemberAt(i); if(device != NULL) {

if(device->getPin() == pin) { return device;

} } } returnNULL; }

~Board() {

delete gatewaysCollection; delete devicesCollection; delete sensorsCollection; delete logger;

} }; }}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Foundation/Logger.hpp namespace Nugraha { namespace Foundation {


(11)

classLogger : public LoggerContract { protected:

DynamicJsonBuffer* jsonBuffer = new DynamicJsonBuffer(); JsonObject* root = &jsonBuffer->createObject();

JsonArray* notifications = &root->createNestedArray("notifications"); JsonArray* measurements = &root->createNestedArray("measurements"); JsonArray* connectionInfos =

&root->createNestedArray("connectionInfos");

bool sendBoardInfo = true;

voidclean() {

delete jsonBuffer;

jsonBuffer = NULL; }

voidreInitializeJsonBuffer() {

jsonBuffer = new DynamicJsonBuffer(); root = &jsonBuffer->createObject();

notifications = &root->createNestedArray("notifications"); measurements = &root->createNestedArray("measurements");

connectionInfos = &root->createNestedArray("connectionInfos"); }

voidaddBoardInfoToRecord() {

JsonObject& boardInfo = root->createNestedObject("boardInfo"); boardInfo["chipId"] = ESP.getChipId();

boardInfo["cpuFreqMHz"] = ESP.getCpuFreqMHz(); boardInfo["sdkVersion"] = ESP.getSdkVersion(); boardInfo["bootVersion"] = ESP.getBootVersion(); boardInfo["bootMode"] = ESP.getBootMode();

boardInfo["cycleCount"] = ESP.getCycleCount(); boardInfo["freeHeap"] = ESP.getFreeHeap(); boardInfo["sketchSize"] = ESP.getSketchSize();

boardInfo["freeSketchSpace"] = ESP.getFreeSketchSpace(); }

public:

void addNotification(int code, String message) {

if(jsonBuffer == NULL)

reInitializeJsonBuffer(); String state;

switch(code) { case0 :

state = "off"; break;

case1 :

state = "on"; break;

default : break; }

JsonObject& notification = notifications->createNestedObject(); notification["pin"] = message;


(12)

notification["state"] = state; }

void addConnectionInfo(String parameter, String value) {

if(jsonBuffer == NULL)

reInitializeJsonBuffer();

JsonObject& connectionInfo = connectionInfos->createNestedObject(); connectionInfo["parameter"] = parameter;

connectionInfo["value"] = value; }

void addSensorMeasurement(String sensorName, String measurementValue) {

if(jsonBuffer == NULL)

reInitializeJsonBuffer();

JsonObject& measurement = measurements->createNestedObject(); measurement["sensor"] = sensorName;

measurement["value"] = measurementValue; }

String getLogMessage() {

if(jsonBuffer != NULL) { if(sendBoardInfo) {

addBoardInfoToRecord(); } String logMessages; root->printTo(logMessages); clean(); reInitializeJsonBuffer(); return logMessages;

} else {

return"{\"records\":[]}"; }

}

void printToSerial() {

if(jsonBuffer != NULL) { if(sendBoardInfo) {

addBoardInfoToRecord(); }

root->prettyPrintTo(Serial); }

else

Serial.println("NULL"); }

}; }}


(13)

namespace Nugraha { namespace Gateways { namespace Esp8266 { using Nugraha::Traits::HasId;

using Nugraha::Traits::HasLogger;

using Nugraha::Contracts::Gateways::GatewayContract; using Nugraha::Contracts::Foundation::BoardContract; using Nugraha::Contracts::Foundation::LoggerContract;

classWifiHttpClient : publicvirtual GatewayContract, public HasLogger, public HasId

{

protected:

ESP8266WiFiMulti WiFiMulti; HTTPClient http;

BoardContract* board;

String ssid = env::wifi::ssid; String password = env::wifi::password;

unsignedlong interval = 1000; String host; String mode; String publishKey; String subscribeKey; String signature; String channelName; String callback;

String message = "{\"text\":\"hello\"}"; String response;

public:

WifiHttpClient(std::map<String, String> setting) {

this->host = setting["host"]; this->mode = setting["mode"];

this->publishKey = setting["publishKey"]; this->subscribeKey = setting["subscribeKey"]; this->signature = setting["signature"];

this->channelName = setting["channelName"]; this->callback = setting["callback"];

}

virtual ~WifiHttpClient() {}

void initialize() {

Serial.println(); Serial.println(); Serial.println();

for(uint8_t t = 4; t >0; t--) {

Serial.printf("[SETUP] WAIT %d...\n", t); Serial.flush();

delay(1000); }

WiFiMulti.addAP("Fugue2", "fugue123"); }


(14)

{

if(message != "") {

String uri = "http://" + host + "/" + mode + "/" + publishKey + "/" + subscribeKey + "/" + signature + "/" + channelName + "/" + callback + "/" + message;

Serial.println(uri); return uri;

} }

template<typename Callback>

void httpGet(String uri, Callback callback) {

// wait for WiFi connection

if((WiFiMulti.run() == WL_CONNECTED)) {

unsignedlong tempMillis = millis(); http.begin(uri);

int httpCode = http.GET(); if(httpCode >0) {

Serial.printf("[HTTP] GET... code: %d\n", httpCode);

// file found at server

if(httpCode == HTTP_CODE_OK) { // Hitung delay.

addDelayToRecord(String(millis() - tempMillis)); // Ekstrak pesan dan panggil fungsi callback.

response = http.getString(); callback();

} else {

addDelayToRecord(String(-1)); }

} else {

Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());

}

http.end(); }

}

int getId() override {HasId::getId();}

void updateMessage() {

this->message = getLogger()->getLogMessage(); }

void setLogger(LoggerContract* logger) override {

HasLogger::setLogger(logger); addDelayToRecord(String(0)); }

LoggerContract* getLogger() {

return logger; }


(15)

void setBoard(BoardContract* board) {

this->board = board; }

void addDelayToRecord(String value) {

getLogger()->addConnectionInfo("delay", value); }

}; }}}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Sensors/Sensor.hpp namespace Nugraha { namespace Sensors {

using Nugraha::Traits::HasId; using Nugraha::Traits::HasLogger;

using Nugraha::Sensors::Drivers::Driver;

using Nugraha::Sensors::Drivers::GenericDriver; using Nugraha::Contracts::Sensors::SensorContract; using Nugraha::Contracts::Foundation::LoggerContract;

classSensor : publicvirtual SensorContract, public HasLogger, public HasId {

protected:

Driver* driver; public:

int id;

int pin;

constchar* name; virtual ~Sensor() {}

Sensor(int pin, constchar* name) { this->pin = pin;

this->name = name;

this->driver = new GenericDriver(); }

int getId() override {HasId::getId();}

void setLogger(LoggerContract* logger) override {HasLogger::setLogger(logger);}

LoggerContract* getLogger() override {HasLogger::getLogger();} };

}}


(16)

namespace Nugraha { namespace Support { namespace Facades { namespace Scheduler {

using Nugraha::Contracts::Support::Facades::Scheduler::EventContract; using Nugraha::Traits::HasId;

classBaseEvent : publicvirtual EventContract, publicvirtual HasId {

protected:

unsignedlong interval;

unsignedlong previousMillis;

int repeatCount = -1; public:

BaseEvent(unsignedlong interval, int repeatCount) {

this->previousMillis = millis(); this->interval = interval;

this->repeatCount = repeatCount; }

virtual ~BaseEvent() {

}

int executionCount = 0;

voidupdate(unsignedlong now) {

if(now - previousMillis >= interval && (repeatCount == -1 || repeatCount >0)) {

previousMillis = now;

Serial.printf("[%d] ", this->id); executeCallback();

if(repeatCount != -1) {

repeatCount--; }

} }

intgetRepeatCount() {

return repeatCount; }

intgetId() override { HasId::getId(); } }; }}}} vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Support/Facades/Scheduler/Scheduler.hpp namespace Nugraha { namespace Support { namespace Facades { namespace Scheduler {

using Nugraha::Collections::Collection;


(17)

classScheduler {

protected:

static CollectionContract<BaseEvent*>* eventCollection; staticbool init;

public:

staticvoid handleEvents() {

if(init) {

after(1, [=](){Serial.println();}); init = false;

}

for(auto event = eventCollection->getMembers().begin(); event != eventCollection->getMembers().end();) {

(*event)->update(millis()); if((*event)->getRepeatCount() == 0) { delete *event;

*event = NULL;

event = eventCollection->getMembers().erase(event); } else {

++event; }

} }

template<typename Callback>

staticvoid every(unsignedlong interval, Callback callback, int

repeatCount = -1) {

eventCollection->add(new StaticEvent<Callback>(interval, callback, repeatCount));

}

template<typename Callback, typename ObjectType>

staticvoid every(unsignedlong interval, ObjectType object, Callback callback, int repeatCount = -1)

{

eventCollection->add(new Event<Callback, ObjectType>(interval, callback, object, repeatCount));

}

template<typename Callback>

staticvoid after(unsignedlong afterMillis, Callback callback) {

every(afterMillis, callback, 1); }

static BaseEvent* getEventAt(int index) {

return eventCollection->getMemberAt(index); }

};

CollectionContract<BaseEvent*>* Scheduler::eventCollection = new Collection<BaseEvent*>();


(18)

}}}}

vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Support/Facades/Scheduler/StaticEvent.hp p

names pac e Nugr aha { names pac e Suppor t { names pac e Fac ades { names pac e Sc hed-ul er {

t empl at e<c l as s Cal l bac k>

c l as s St at i c Ev ent : publ i c v i r t ual Bas eEv ent {

pr ot ec t ed:

Cal l bac k c al l bac k ;

publ i c:

St at i c Ev ent (uns i gned l ong i nt er v al , Cal l bac k c al l bac k , i nt r epeat Count ) : Bas eEv ent ( i nt er v al , r epeat Count ) , c al l bac k ( c al l bac k )

{ }

v oi d ex ec ut eCal l bac k ( ) {

t hi s- >c al l bac k ( ) ; }

} ; } } } }


(19)

LAMPIRAN 2

KODE PROGRAM APLIKASI WEB

App/Http/routes.php

<?php

Rout e: :get(' / ' , ' HomeCont r ol l er @i ndex ' ) ; Rout e: :aut h( ) ;

Rout e: :get(' publ i s h/ { publ i s hKey } / { s ubs c r i beKey } / { s i gnat ur e} / { c hannel Name} / { c al l bac k } / { mes s age} ' , ' Publ i s hCont r ol l er @handl e' ) ;

Rout e: :get(' manage/ das hboar d' , ' Das hboar dCont r ol l er @i ndex ' ) ;

Rout e: :get(' manage/ das hboar d/ c ons ol e' , ' Cons ol eCont r ol l er @i ndex ' ) ; Rout e: :get(' not i f i c at i ons ' , ' Not i f i c at i ons Cont r ol l er @i ndex ' ) ; Rout e: :get(' not i f i c at i ons / { not i f i c at i ons } / s een' ,

' Not i f i c at i ons Cont r ol l er @s een' ) ;

Rout e: :get(' meas ur ement s ' , ' Meas ur ement s Cont r ol l er @i ndex ' ) ; Rout e: :get(' meas ur ement s / { meas ur ement s } / s een' ,

' Meas ur ement s Cont r ol l er @s een' ) ;

Rout e: :get(' c onnec t i oni nf os ' , ' Connec t i onI nf os Cont r ol l er @i ndex ' ) ; Rout e: :get(' c onnec t i oni nf os / { c onnec t i oni nf os } / s een' ,

' Connec t i onI nf os Cont r ol l er @s een' ) ;

Rout e: :get(' c ommands / 1/ { pi n} ' , ' Commands Cont r ol l er @t ur nOn' ) ; Rout e: :get(' c ommands / 0/ { pi n} ' , ' Commands Cont r ol l er @t ur nOf f ' ) ;

App/Http/Controllers/CommandsController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Command;

use App\Http\Requests;

use Illuminate\Http\JsonResponse; use Carbon\Carbon;

use App\Traits\ArduinoBoard;

classCommandsControllerextends Controller {

use ArduinoBoard; functionturnOn($pin) {

$command = new Command();

$command->pin = $this->getPinValue($pin);

$command->action = 'turnOn';

$command->save(); }


(20)

functionturnOff($pin) {

$command = new Command();

$command->pin = $this->getPinValue($pin);

$command->action = 'turnOff';

$command->save(); }

}

App/Http/Controllers/ConnectionInfosController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests;

use App\ConnectionInfo;

use Illuminate\Http\JsonResponse;

classConnectionInfosControllerextends Controller {

functionindex() {

$connectionInfos = ConnectionInfo::where('seen', false)->get()->

toArray();

return (new JsonResponse(array( "connectionInfos" =>$connectionInfos

))); }

functionseen(ConnectionInfo $connectionInfo) {

$connectionInfo->seen = true;

$connectionInfo->save();

} }

App/Http/Controllers/ConsoleController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests;

use App\Command; use App\Measurement; use App\Notification;

use Illuminate\Http\JsonResponse;


(21)

{

functionindex() {

return view('dashboard.console.index'); }

}

App/Http/Controllers/DashboardController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests;

classDashboardControllerextends Controller {

publicfunction__construct() {

$this->middleware('auth');

}

publicfunctionindex() {

return view('dashboard.index'); }

}

App/Http/Controllers/HomeController.php <?php

namespace App\Http\Controllers; use App\Http\Requests;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Redirect; use App\TugasAkhirWahyu\TugasAkhirWahyu; classHomeControllerextends Controller {

publicfunction__construct() {

}

publicfunctionindex() {


(22)

} }

App/Http/Controllers/MeasurementsController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Measurement;

use Illuminate\Http\JsonResponse;

classMeasurementsControllerextends Controller {

functionindex() {

$notifications = Measurement::where('seen', false)->get()->toArray(); return (new JsonResponse(array(

"measurements" =>$notifications

))); }

functionseen(Measurement $measurement) {

$measurement->seen = true;

$measurement->save(); }

}

App/Http/Controllers/NotificationsController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Notification;

use Illuminate\Http\JsonResponse;

classNotificationsControllerextends Controller {

functionindex() {

$notifications = Notification::where('seen', false)->get()->toArray(); return (new JsonResponse(array(

"notifications" =>$notifications

))); }

functionseen(Notification $notification) {

$notification->seen = true;

$notification->save(); }


(23)

App/Http/Controllers/PublishController.php <?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; use Carbon\Carbon;

use App\Http\Requests; use App\Command;

use App\Notification; use App\Device;

use App\Measurement; use App\ConnectionInfo;

classPublishControllerextends Controller {

functionhandle($publishKey, $subscribeKey, $signature, $channelName,

$callback, $message)

{

if($publishKey != "pub-w-3e5de365-5d57-48c7-a317-366ef2846eb4" ||

$subscribeKey != "sub-n-cca59b64-d972-11e5-bdd5-02ee2ddab7fe") {

return []; }

$this->saveMessages($message);

return$this->sendResponse(); }

functionsaveMessages($message) {

$data = json_decode($message);

$myNotification;

foreach ($data->notificationsas$notification) {

$myNotification = new Notification();

$myNotification->pin = $notification->pin;

$myNotification->state = $notification->state;

$myNotification->seen = false;

$myNotification->save();

$device = Device::where('pin', $myNotification->pin)->get()-> first();

if(isset($device->state)){

if($notification->state == 'on') {

$device->state = true;

} elseif($notification->state == 'off') {

$device->state = false; }

$device->save(); } }

$myMeasurements;

foreach ($data->measurementsas$measurement) {

$myMeasurements = new Measurement();


(24)

$myMeasurements->value = $measurement->value;

$myMeasurements->seen = false;

$myMeasurements->save();

}

$myConnectionInfos;

foreach ($data->connectionInfosas$connectionInfo) {

$myConnectionInfos = new ConnectionInfo();

$myConnectionInfos->parameter = $connectionInfo->parameter;

$myConnectionInfos->value = $connectionInfo->value;

$myConnectionInfos->seen = false;

$myConnectionInfos->save();

} }

functionsendResponse() {

$commands = Command::where('sent', false)->get();

foreach ($commandsas$command) {

$command->sent = true;

$command->sent_at = Carbon::now();

$command->save(); }

return (new JsonResponse(array("commands" =>$commands->

toArray())));

} }

Resources/views/dashboard/index.blade.php @extends('dashboard.layouts.master') @section('content')

<div class="row x_title"> <div class="col-md-6">

<h3>Rumah <small>saya</small></h3> </div>

<div class="col-md-6"> </div>

</div>

<div class="col-md-12 col-sm-12 col-xs-12"> <table class="table table-inverse">

<thead> <tr> <th>#</th> <th>Nama</th> <th>Pin</th> <th>Action</th> </tr> </thead> <tbody>


(25)

<tr>

<th scope="row">1</th> <td>A/C</td>

<td>D6</td> <td>

<button id="turnOn1" type="button" class="btn btn-primary">On</button> <button id="turnOff1" type="button" class="btn btn-warning">Off</button> </td>

</tr> <tr>

<th scope="row">2</th> <td>Lampu 1</td>

<td>D2</td> <td>

<button id="turnOn2" type="button" class="btn btn-primary">On</button> <button id="turnOff2" type="button" class="btn btn-warning">Off</button> </td>

</tr> <tr>

<th scope="row">3</th> <td>Lampu 2</td>

<td>D3</td> <td>

<button id="turnOn3" type="button" class="btn btn-primary">On</button> <button id="turnOff3" type="button" class="btn btn-warning">Off</button> </td>

</tr> <tr>

<th scope="row">4</th> <td>Lampu 3</td>

<td>D4</td> <td>

<button id="turnOn4" type="button" class="btn btn-primary">On</button> <button id="turnOff4" type="button" class="btn btn-warning">Off</button> </td>

</tr> <tr>

<th scope="row">5</th> <td>Lampu 4</td>

<td>D5</td> <td>

<button id="turnOn5" type="button" class="btn btn-primary">On</button> <button id="turnOff5" type="button" class="btn btn-warning">Off</button> </td>

</tr> <tr>

<th scope="row">6</th> <td>Test Led</td> <td>BUILTIN_LED</td> <td>

<button id="turnOn6" type="button" class="btn btn-primary">On</button> <button id="turnOff6" type="button" class="btn btn-warning">Off</button> </td> </tr> </tbody> </table> </div> <script>


(26)

// A/C

$('#turnOn1').click(function() {

$.ajax({url: "/commands/1/d6", success: function(result) {alert("Perintah terkirim!");}});

});

$('#turnOff1').click(function() {

$.ajax({url: "/commands/0/d6", success: function(result) {alert("Perintah terkirim!");}});

});

// Lampu 1

$('#turnOn2').click(function() {

$.ajax({url: "/commands/1/d2", success: function(result) {alert("Perintah terkirim!");}});

});

$('#turnOff2').click(function() {

$.ajax({url: "/commands/0/d2", success: function(result) {alert("Perintah terkirim!");}});

});

// Lampu 2

$('#turnOn3').click(function() {

$.ajax({url: "/commands/1/d3", success: function(result) {alert("Perintah terkirim!");}});

});

$('#turnOff3').click(function() {

$.ajax({url: "/commands/0/d3", success: function(result) {alert("Perintah terkirim!");}});

}); // Lampu 3

$('#turnOn4').click(function() {

$.ajax({url: "/commands/1/d4", success: function(result) {alert("Perintah terkirim!");}});

});

$('#turnOff4').click(function() {

$.ajax({url: "/commands/0/d4", success: function(result) {alert("Perintah terkirim!");}});

}); // Lampu 4

$('#turnOn5').click(function() {

$.ajax({url: "/commands/1/d5", success: function(result) {alert("Perintah terkirim!");}});

});

$('#turnOff5').click(function() {

$.ajax({url: "/commands/0/d5", success: function(result) {alert("Perintah terkirim!");}});

}); // Test Led

$('#turnOn6').click(function() {

$.ajax({url: "/commands/1/builtin_led", success: function(result) {alert("Perintah terkirim!");}});

});

$('#turnOff6').click(function() {

$.ajax({url: "/commands/0/builtin_led", success: function(result) {alert("Perintah terkirim!");}});

}); });


(27)

</script> @endsection

Resources/views/dashboard/console/index.blade.php @extends('dashboard.layouts.master') @section('content')

<div class="row x_title"> <div class="col-md-6">

<h3>Debug <small>Console</small></h3> </div>

<div class="col-md-6"> </div>

</div>

<div class="col-md-12 col-sm-12 col-xs-12"> <div id="ayam" class="col-md-6">

</div>

<div id="console" class="col-md-6">

<textarea class="col-md-12" id="myConsoleArea" cols="100" rows="9000" style="background:#000; foreground:#fff; height: 700px;

font-size:16px"></textarea> </div>

</div> <script>

var message = ""; functiongetData() {

$.ajax({url: "/notifications", success: function(result) { result.notifications.forEach(function(notification) {

message += '>> ['+ notification.created_at +'] perangkat pada pin ' + notification.pin + ' telah di-' + notification.state + '-kan\n';

$('#myConsoleArea').html(message);

$.ajax({url: "/notifications/"+notification.id+"/seen", success: function(result) {}});

});; }});

$.ajax({url: "/measurements", success: function(result) { result.measurements.forEach(function(measurement) {

message += '>> ['+ measurement.created_at +'] pembacaan sensor ' + measurement.sensor + ' adalah: ' + measurement.value + '\n';

$('#myConsoleArea').html(message);

$.ajax({url: "/measurements/"+measurement.id+"/seen", success: function(result) {}});

});; }});

setTimeout(getData, 3000); }

$(document).ready(function () { getData();

});

</script> @endsection


(28)

Resources/views/dashboard/layouts/master.blade.php <!DOCTYPE html>

<html lang="en"> <head>

@include('dashboard.layouts.master.header') @yield('header')

</head>

<body class="nav-md">

<div class="container body"> <div class="main_container"> <div class="col-md-3 left_col"> <div class="left_col scroll-view">

<div class="navbar nav_title" style="border: 0;"> <a href="dashboard" class="site_title"><i class="fa fa-paw"></i><span>Dashboard</span></a>

</div>

<div class="clearfix"></div> <!-- menu profile quick info --> <div class="profile">

@include('dashboard.layouts.master.profileQuickInfo') </div>

<!-- /menu profile quick info --> <br />

<!-- sidebar menu -->

<div id="sidebar-menu" class="main_menu_side hidden-print main_menu"> <div class="menu_section">

@include('dashboard.layouts.master.sideBarMenu') </div>

</div>

<!-- /sidebar menu -->

<!-- /menu footer buttons -->

<div class="sidebar-footer hidden-small">

@include('dashboard.layouts.master.menuFooterButtons') </div>

<div class="clearfix"></div> <!-- /menu footer buttons --> </div>


(29)

<!-- top navigation --> <div class="top_nav"> <div class="nav_menu">

<nav class="" role="navigation"> <div class="nav toggle">

<a id="menu_toggle"><i class="fa fa-bars"></i></a> </div>

@include('dashboard.layouts.master.topNavigation') </nav>

</div> </div>

<!-- /top navigation --> <!-- page content -->

<div class="right_col" role="main"> <div class="row">

<div class="col-md-12 col-sm-12 col-xs-12"> <div class="dashboard_graph">

@yield('content') <div class="clearfix"></div>

</div> </div> </div> <br/>

<!-- footer content --> <footer>

@include('dashboard.layouts.master.footer') @yield('footer')

</footer>

<!-- /footer content --> </div>

<!-- /page content --> </div>

</div>

<div id="custom_notifications" class="custom-notifications dsp_none"> <ul class="list-unstyled notifications clearfix"

data-tabbed_notifications="notif-group"> </ul>

<div class="clearfix"></div>

<div id="notif-group" class="tabbed_notifications"></div> </div>

@include('dashboard.layouts.master.scripts') </body>


(30)

DAFTAR PUSTAKA

[1] D. Miorandi, S. Sicari, F. D. Pellegrini and I. Chlamtac, "Internet of things: Vision, applications and research challenges," Ad Hoc Networks, p. 1497– 1516, 2012.

[2] R. Teymourzadeh, S. A. Ahmed, K. W. Chan and M. V. Hoong, "Smart GSM Based Home Automation System," in IEEE Conference on Systems, Process & Control, Kuala Lumpur, 2013.

[3] M. Margolis, Arduino Cookbook, Sebastopol: O’Reilly, 2012. [4] C. Hunt, TCP/IP Network, Sebastopol: O’Reilly, 2002.

[5] K. R. Fall and W. R. Stevens, TCP/IP Illustrated, Volume 1, Michigan: Addison-Wesley, 2012.

[6] M. S. Gast, 802.11© Wireless Networks: The Definitive Guide, Second Edition, Sebastopol: O'Reilly, 2005.

[7] D. Gourley and B. Totty, HTTP: The Definitive Guide, Sebastopol: O’Reilly, 2002.

[8] J. Lockhart, Modern PHP, Sebastopol: O’Reilly, 2015.

[9] R. Lafore, Object-Oriented Programming in C++, Fourth Edition, Indianapolis: Sams, 2002.


(31)

BAB 3

METODE PENELITIAN

3.1 Gambaran Umum

Model sistem Home Automation dirancang menggunakan Wemos D1 yang telah teringrasi dengan modul Wi-Fi. Wemos D1 setiap saatnya melakukan kontrol perangkat yang tersambung dengannya, seperti apakah perangkat harus dihidupkan atau dimatikan pada nilai pembacaan sensor tertentu. Selain itu

Wemos D1 juga mengumpulkan data pembacaan sensor dan status dari setiap perangkat kemudian mengirimkan sebuah request HTTP dengan memasukkan semua data tersebut ke pesan request.

Smartphone Komputer

Mengirim data dan menerima perintah Menerima data dan mengirim perintah

Menerima data dan mengirim perintah

Perangkat

Mengontrol perangkat sesuai dengan kondisi sensor dan perintah yang diterima.

Gambar 3.1 Gambaran umum sistem. Internet


(32)

Ketika request diterima dibagian server, sebuah pesan respon yang berisi kumpulan perintah dari user akan dikirimkan kembali ke Wemos D1. Kemudian

Wemos D1 akan mengekstrak perintah yang ada pada pesan respon tersebut dan mengeksekusinya. Secara kesluruhan bentuk sistem Home Automation yang dirancang adalah seperti yang terlihat pada Gambar 3.1.

3.2 Spesifikasi

Sistem Home Automation yang dirancang terdiri dari beberapa komponen. Berikut adalah penjelasan dan spesifikasi dari komponen – komponen yang diguanakan.

3.2.1 Server

Server pada sistem Home Automation yang dirancang menggunakan layanan Virtual Private Server (VPS) dari DigitalOcean.com. Server yang digunakan mempunyai CPU 1 core dengan frekuensi 2.4GHZ, RAM sebesar 512 MB, dan Hard Disk sebesar 20 GB. Sistem operasi yang digunakan pada server

adalah Ubuntu 14.04. Untuk menjalankan layanan server, aplikasi yang digunakan oleh komputer server adalah Apache/2.4.7, MySQL14.14, dan PHP 5.5.9.

3.2.2 Controller

Kontroler yang di gunakan pada sistem Home Automation yang dirancang adalah Wemos D1 yang merupakan sebuah clone Board Arduino Uno yang dilengkapi sebuah modul Wi-Fi ESP8266. Board ini mempunyai 11 pin digital


(33)

micro USB, sebuah power jack dengan input 9-24 Volt. Penampang Board ini adalah seperti yang ditunjukkan pada Gambar 3.2.

Gambar 3.2Wemos D1 Spesifikasi dari Wemos D1 adalah sebagai berikut:

Tabel 3.1Spesifikasi Wemos D1

Parameter Nilai

Operating Voltage 3.3V

Digital I/O Pins 11

Analog Input Pins 1(Max input: 3.2V)

Clock Speed 80MHz/160MHz

Flash 4M bytes

Panjang 68.6 mm

Lebar 53.4 mm

Berat 25g

3.2.3 Modul Relay 4 Kanal

Modul relay yang digunakan adalah sebuah modul relay yang memiliki 4 kanal. Modul relay tersebut ditunjukkan pada Gambar 3.3.


(34)

Gambar 3.3Modul relay empat kanal

Modul relay tersebut terdiri dari 4 buah relay magnetik dan beberapa komponen tambahan untuk proteksi. Modul tersebut dapat langsung dikendalikan menggunakan sinyal digital sebuah Controller seperti Arduino. Modul tersebut juga mempunyai sebuah LED indikator untuk setiap relay. Modul relay ini dapat menangani arus maksimal 10 ampere AC dan tegangan 250-volt AC. Selain dapat menangani arus dan tegangan AC, relay ini juga dapat menangani arus dan tengan DC dengan nilai maksimum masing – masing 10 ampere dan 30-volt DC. Skematik dari modul tersebut adalah seperti yang terlihat pada Gambar 3.4.


(35)

3.2.4 Stop Contact

Stop Contact yang digunakan adalah Stop Contact yang mempunyai empat buah lubang masukan. Masing – masing lubang masukan dapat mengantar arus maksimum 16 ampere AC. Pada dasarnya keempat lubang masukan terhubung paralel dengan sumber masukan seperti yang ditunjukkan pada Gambar 3.5.

Gambar 3.5 Hubungan paralel keempat lubang stop contact 3.2.5 Sensor Passive Infrared

Sensor pendeteksi pergerakan yang digunakan pada sistem Home Automation yang dirancang adalah Sensor PIR (Passive Infra Red) yang merupakan sensor yang digunakan untuk mendeteksi adanya pancaran sinar infra merah. Sensor PIR bersifat pasif, artinya sensor ini tidak memancarkan sinar infra merah tetapi hanya menerima radiasi sinar infra merah dari luar. Bentuk dari sensor PIR ditunjukkan pada Gambar 3.6.


(36)

Sensor ini biasanya digunakan dalam perancangan detektor gerakan berbasis PIR. Karena semua benda memancarkan energi radiasi, sebuah gerakan akan terdeteksi ketika sumber infra merah dengan suhu tertentu (seperti manusia) melewati sumber infra merah yang lain dengan suhu yang berbeda (seperti dinding), maka sensor akan membandingkan pancaran infra merah yang diterima setiap satuan waktu, sehingga jika ada pergerakan maka akan terjadi perubahan pembacaan pada sensor. Spesifikasi sensor PIR yang digunakan seperti yang terlihat pada Tabel 3.2.

Tabel 3.2 Spesifikasi sensor PIR yang digunakan

Parameter Keterangan

Output Pulsa digital high (3V)

Jarak sensitif 6 meter

Power Supply 3V-9V, tapi yang ideal 5V

3.2.6 Sensor Suhu

Sensor Suhu atau Temperature Sensors adalah suatu komponen yang dapat mengubah besaran panas menjadi besaran listrik sehingga dapat mendeteksi gejala perubahan suhu pada objek tertentu. Sensor suhu melakukan pengukuran terhadap jumlah energi panas/dingin yang dihasilkan oleh suatu obyek sehingga memungkinkan untuk mengetahui atau mendeteksi gejala perubahan-perubahan suhu tersebut dalam bentuk output Analog maupun Digital. Sensor Suhu juga merupakan dari keluarga Transduser. Sensor suhu yang digunkan pada sistem

Home Automation yang dirancang adalah sensor suhu digital DS18S20. Sensor ini mampu mengukur temperatur pada rentang -55 sampai 100 derajat selsius. Bentuk dari sensor ini seperti yang terlihat pada Gambar 3.7.


(37)

Gambar 3.7 Sensor suhu DS18S20

3.3 Cara kerja

Cara kerja dari model sistem Home Automation yang dirancang adalah sebagai berikut:

a) Sistem Home Automation terdiri dari sebuah Board Arduino yang terhubung ke sebuah rangkaian relay dengan skematik seperti yang terlihat pada Gambar 3.4 dan beberapa sensor. Rangkaian relay yang digunakan mempunyai 4 kanal dan akan menjadi saklar bagi sumber tegangan 220 volt sehingga perangkat apapun seperti lampu, kipas dan sebagainya dapat disambungkan ke rangkaian relay

tersebut.

b) Board arduino kemudian terhubung ke sebuah modul Wi-Fi agar sistem Home Automation dapat terhubung ke internet. Pada bagian Software-nya sebuah aplikasi web digunakan untuk memberikan fungsi kendali pada sistem Home Automation yang dapat dilakukan dari sebuah PC atau smartphone. Software

ini juga berguna untuk menyimpan dan menampilkan data pembacaan sensor. c) Sistem akan mulai bekerja pada saat Arduino disambungkan ke catu daya.

Pertama Arduino akan melakukan beberapa rutin inisialisasi seperti inisialisasi Wi-Fi dan inisialisasi beberapa sensor dan perangkat yang disambungkan padanya. Setiap perangkat yang disambungkan pada Arduino dimodelkan menjadi sebuah objek dalam bahasa C++, dimana objek ini


(38)

beberapa memiliki properti utama seperti: pin yang menyatakan nomor pin

Board Arduino dimana perangkat ini terhubung; sensor, merupakan sebuah objek C++ yang memodelkan sensor yang digunakan sebagai dasar pengambilan keputusan oleh Arduino pada perangkat tersebut.

d) Setelah tahap inisialisasi selesai, Arduino akan selalu memantau pembacaan sensor – sensor dari setiap perangkat dan melakukan tindakan pada perangkat tersebut berdasar nilai pembacaan yang didapat. Arduino setiap saatnya juga melakukan komunikasi dengan webserver seperti meng-upload pembacaan sensor-sensor, mengambil perintah dari user dan mengeksekusinya jika ada. Aplikasi web yang dirancang pada dasarnya berfungsi untuk monitoring, notifikasi, dan juga untuk memberikan fungsi kendali manual.

e) Gambar 3.8menunjukkan diagram alir sistem secara keseluruhan.


(39)

(40)

3.4 Rancangan Bagian Hardware

Pada bagian hardware, sistem Home Automation yang dirancang terdiri dari sebuah Wemos D1 ESP8266 yang merupakan sebuah clone dari Board Arduino yang dilengkapi sebuah modul Wi-Fi ESP8266. Wemos D1 akan menjadi pengendali bagi setiap yang terhubung ke pin-pinnya. Dalam hal ini perangkat yang terhubung ke Wemos D1 adalah sebuah modul relay 4 kanal yang digunakan untuk mengontrol sebuah stop contact 4 lubang. Untuk mendapatkan kemampuan otomasi, dua buah sensor juga disambungkan ke Wemos D1. Sensor tersebut adalah sensor passive infrared dan sensor suhu.

Agar stop contact dapat dikendalikan oleh BoardController maka harus dilakukan modifikasi pada pengkabelannya hingga menjadi seperti yang terlihat pada Gambar 3.9.

Gambar 3.9Modifikasi pengkabelan stop contact


(41)

Bentuk keterhubungan seluruh perangkat yang ada pada sistem Home Automaton yang dirancang adalah seperti yang terlihat pada Gambar 3.10.

Gambar 3.10 Keterhubungan perangkat – perangkat menjadi sistem Home Automation

3.5 Rancangan SoftwareControler

Controller sistem Home Automation yang merupakan sebuah Wemos D1, diprogram dengan menggunakan bahasa C++. Program pada ControllerHome Automation yang dirancang terdiri dari beberapa sub bagian yang dibagi menjadi

classclass program. Class tersbut adalah classController, classScheduler,

classCollection, classBoard, classDevice, class Sensor, dan

classGateway.Hubungan antar class yang ada pada program controller adalah seperti yang terlihat pada Gambar 3.11.


(42)

Board -services -devices -sensors +initialize () +automate () Service -interval +service () Device -pin +behavior () Sensor -pin +readMeasurementValue () HttpClient +service () PingLogger +service () TemperatureLogger +service () Lampu +behavior () AirConditioner +behavior () Ds18B20 +readMeasurementValue () PirSensor +readMeasurementValue () Controller +setup () +loop () -memberName ServiceContract +getId() +service() +setLogger() +getLogger() DeviceContract +turnOn() +turnOff() +toggle() +behavior() +getId() +setLogger() +getLogger() SensorContract +getId() +readMeasurementValue() +setLogger() +getLogger()

Gambar 3.11 Diagram hubungan antar class program controller 3.5.1 ControllerClass

ControllerClassmerupakanclassutama dimana fungsi setup dan fungsi dari

class ini akan menjadi fungsi setup dan fungsi loop yang akan dijalankan oleh

Wemos D1. Class ini meng-extendsclass BaseController yang merupakan sebuah

classcontract untuk seluruh classController, dimana class Base Controller

mempunyai fungsi virtual yang harus diimplementasikan oleh setiap anak class

yang meng-extends class ini. Isi dari class Base Controller adalah seperti yang terlihat pada Gambar 3.12.


(43)

1 c l as s Bas eCont r ol l er

2 { 3 publ i c:

4 Boar dCont r ac t * boar d; 5 v i r t ual v oi d s et up( ) =0; 6 v i r t ual v oi d l oop( ) =0; 7 } ;

Gambar 3.12 Kode Program class BaseController

ClassController sendiri berisi implementasi dari fungsi virtual yang ada di

class Base Controller. Fungsi – fungsi virtual tersebut adalah fungsi setup dan fungsi loop. Pada fungsi setup berisi statement untuk inisialisasi Wemos D1 serta inisialisasi modul Wi-Fi. Pada fungsi loop berisi perintah untuk melakukan eksekusi untuk setiap event yang didaftarkan pada classScheduler. Isi dari

classController tersebut seperti yang ditunjukkan pada Gambar 3.13. 1 c l as s Cont r ol l er : publ i c v i r t ual Bas eCont r ol l er 2 {

3 publ i c:

4 v oi d s et up( ) 5 {

6 Debug: : i s DebugMode = t r ue;

7 Wi Fi . c onf i g( env : : wi f i : : i p, env : : wi f i : : gat eway , env : : wi f i : : s ubnet , env : : wi f i : : dns 1,

env : : wi f i : : dns 2) ; 8 boar d- >i ni t i al i z e( ) ; 9 boar d- >aut omat e( ) ; 10 }

11

12 v oi d l oop( ) 13 {

14 Sc hedul er: : handl eEv ent s ( ) ; 15 }

16 } ;

Gambar 3.13 Kode program classController 3.5.2 Collection Class

CollectionClass merupakan sebuah class yang bertanggung jawab untuk manajemen kumpulan beberapa object. ClassCollectionyang digunakan pada


(44)

Sistem Home Automation yang dirancang pada dasarnya adalah sebuah wrapper

untuk Class std::vector. ClassCollection harus meng-extends

classCollectionContract dengan kode seperti yang ditunjukkan pada Gambar 3.14. 1 names pac e Nugr aha { names pac e Cont r ac t s { names pac e Col l ec t i ons { 2

3 t empl at e <c l as s Member s Ty pe> 4 c l as s Col l ec t i onCont r ac t

5 { 6 publ i c:

7 v i r t ual v oi d add( Member s Ty pe newMember ) =0; 8 v i r t ual v oi d r emov eAt (i nt i ndex ) =0;

9 v i r t ual i nt c ount ( ) =0;

10 v i r t ual Member s Ty pe get Member At (i nt i ndex ) =0; 11 } ;

12 13 } } }

Gambar 3.14 Kode program classCollectionContract

Terdapat empat fungsi virtual yang harus diimplementasikan oleh Class

yang meng-extends classCollectionContract yaitu: fungsi add yang merupakan fungsi untuk menambahkan anggota baru ke koleksi; fungsi removeAt yang merupakan fungsi untuk menghapus anggoa koleksi pada indeks tertentu; fungsi count yang merupakan fungsi untuk mendapatkan total jumlah anggota yang ada di dalam koleksi;fungsi getMemberAt yang merupakan sebuah fungsi untuk mendapatkan anggota koleksi pada indeks tertentu. ClassCollectionContract diimplementasikan pada classCollection seperti yang terlihat pada Gambar 3.15.


(45)

1 c l as s Col l ec t i on : publ i c v i r t ual Col l ec t i on<Member s Ty pe> { 2 pr ot ec t ed:

3 s t d: : v ec t or <Member s Ty pe> member s ; 4

5 publ i c:

6 i nt c ount ( ) 7 {

8 r et ur n member s .s i z e( ) ; 9 }

10

11 v oi d add( Member s Ty pe newMember ) 12 {

13 member s . pus h_bac k ( newMember ) ; 14 }

15

16 v oi d r emov eAt (i nt i ndex ) 17 {

18 member s . er as e( member s .begi n( ) + i ndex ) ; 19 }

20

21 Member s Ty pe get Member At (i nt i ndex ) 22 {

23 i f( i ndex >= 0 && i ndex < member s .s i z e( ) ) { 24 r et ur n member s [ i ndex ] ;

25 }

26 r et ur n NULL; 27 }

28 } ;

Gambar 3.15 Kode program class koleksi Vector

3.5.3 SchedulerClass

SchedulerClassmerupakan sebuah class yang bertanggung jawab untuk pengeksekusian events yang dieksekusi berdasarkan interval waktu. Penggunaan fungsi delay bisa saja digunakan untuk mendapatkan hasil yang serupa, namun pada penggunaan delay, Wemos D1 akan benar – benar tidak melakukan apa – apa selama selang delay tersebut. Hal ini sangat tidak efisien karena Wemos D1 tidak akan dapat mengontrol perangkat yang lain selama periode delay tersebut.

ClassScheduler mempunyai sebuah koleksi event dan beberapa fungsi pendukung. Fungsi – fungsi tersebuat antara lain: fungsi every yang berguna


(46)

untuk mendaftarkan sebuah perintah dan mengeksekusi perintah tersebut setiap

interval tertentu, fungsi handleEvents yang bertanggung jawab untuk mengupdate

timer setiap event dan mengeksekusi event tersebut jika waktu ketika fungsi ini dipanggil di kurang dengan waktu yang direkam sebelumnya lebih besar atau sama dengan interval yang ditentukan untuk event tersebut. Kerangka

ClassScheduler yang digunakan pada sistemHome Automationyang dirancang dapat dilihat pada Gambar 3.16.

1 c l as s Sc hedul er

2 {

3 pr ot ec t ed:

4 s t at i c Col l ec t i on<Bas eEv ent * >* Ev ent Col l ec t i on; 5

6 publ i c:

7 t empl at e<t y pename Cal l bac k >

8 s t at i c v oi d ev er y (uns i gned l ong i nt er v al , Cal l bac k c al l bac k ,

i nt r epeat Count = -1) 9 {

10 Ev ent Col l ec t i on- >add(new St at i c Ev ent <Cal l bac k >( i nt er v al , c al l bac k ) ) ;

11 } 12

13 t empl at e<t y pename Cal l bac k , t y pename Obj ec t Ty pe>

14 s t at i c v oi d ev er y (uns i gned l ong i nt er v al , Obj ec t Ty pe obj ec t , Cal l bac k c al l bac k , i nt r epeat Count = -1)

15 {

16 Ev ent Col l ec t i on- >add(new Ev ent <Cal l bac k , Obj ec t Ty pe>( i nt er v al , c al l bac k , obj ec t ) ) ; 17 }

18

19 s t at i c v oi d handl eEv ent s ( ) 20 {

21 f or(i nt i =0; i <Ev ent Col l ec t i on- >c ount ( ) ; i ++) 22 {

23 Ev ent Col l ec t i on- >get Member At ( i ) - >updat e(mi l l i s( ) ) ; 24 }

25 } 26 } ;


(47)

Class Event yang ada pada classScheduler adalah sebuah class yang meng-extends class BaseEvent dan EventContract. Class tersebut mempunyai fungsi executeCallback yang akan mengesekusi callback yang telah ditentukan. Class

Event dapat dilihat pada Gambar 3.17. 1 t empl at e<c l as s Cal l bac k>

2 c l as s St at i c Ev ent : publ i c v i r t ual Bas eEv ent 3 {

4 pr ot ec t ed:

5 Cal l bac k c al l bac k ; 6

7 publ i c:

8 St at i c Ev ent (uns i gned l ong i nt er v al , Cal l bac k c al l bac k ) : ___________c al l bac k ( c al l bac k )

9 {

10 t hi s- >i nt er v al = i nt er v al ; 11 }

12

13 v oi d ex ec ut eCal l bac k ( ) 14 {

15 t hi s- >c al l bac k ( ) ; 16 }

17 } ;

Gambar 3.17 Kode program class StaticEvent

3.5.4 BoardClass

BoardClassmerupakanclass yang memodelkan perangkat Wemos D1. Pada

class ini sebuah fungsi attach dapat digunakan untuk menyambungkan instance

dari ClassGateway, ClassDevice atau Class Sensor pada instance classBoard

seperti yang terlihat pada Kode Program berikut. ClassWemos D1 merupakan extend dari classBoardContract. Class WemosD1 harus mengimplementasikan tiga fungsi virtual yang ada pada classBoardContract. Ketiga fungsi tersebut adalah fungsi fungsi Gateways, fungsi Devices dan fungsi sensors. Dimana fungsi

Gateways adalah fungsi dimana seluruh Gateway yang ingin disambungkan ke


(48)

yang ingin disambungkan ke WemosD1 didaftarkan, begitu juga dengan fungsi sensors yang merupakan tempat dimana seluruh sensor yang ingin disambungkan ke WemosD1 didaftarkan. Class WemosD1 lebih jelasnya dapat dilihat pada Gambar 3.18.

1 c l as s Wemos D1 : publ i c v i r t ual Boar d { 2 pr ot ec t ed:

3 v oi d gat eway s ( ) 4 {

5 t hi s- >at t ac hGat eway (new Per s i s t ent Ht t p( s t d: :map<St r i ng,

St r i ng>( {

6 { " hos t " , env : : ht t pCl i ent : : hos t } , 7 { " mode" , env : : ht t pCl i ent : : mode } ,

8 { " publ i s hKey " , env : : ht t pCl i ent : : publ i s hKey } , 9 { " s ubs c r i beKey " , env : : ht t pCl i ent : : s ubs c r i beKey } , 10 { " s i gnat ur e" , env : : ht t pCl i ent : : s i gnat ur e } , 11 { " c hannel Name" , env : : ht t pCl i ent : : c hannel Name } , 12 { " c al l bac k " , env : : ht t pCl i ent : : c al l bac k } 13 } ) ) ) ;

14 }

15 v oi d dev i c es ( ) 16 {

17 t hi s- >at t ac hDev i c e(new Ai r Condi t i oner ( D13, NULL) ) ; 18 t hi s- >at t ac hDev i c e(new Led( BUI LTI N_LED, NULL) ) ; 19 }

20 v oi d s ens or s ( ) 21 {

22 t hi s- >at t ac hSens or (new Sens or Suhu( D12) ) ; 23 }

24 } ;

Gambar 3.18 Kode program class Wemos D1

3.5.5 DeviceClass

DeviceClassmerupakanclass yang memodelkan perangkat yang terhubung ke WemosD1. Class ini memungkinkan proses manipulasi perangkat menjadi lebih mudah. Class ini merupakan extend dari classDeviceContract, dimana pada

classcontract tersebut terdapat 7 fungsi virtual yang harus diimplementasikan oleh classDevice. ClassDeviceContract ditunjukkan pada Gambar 3.19.


(49)

1 c l as s Dev i c eCont r ac t

2 { 3 publ i c:

4 v i r t ual v oi d t ur nOn( ) =0; 5 v i r t ual v oi d t ur nOf f ( ) =0; 6 v i r t ual v oi d behav i or ( ) =0; 7 v i r t ual v oi d i ni t i al i z e( ) =0; 8 v i r t ual i nt get Pi n( ) =0;

9 v i r t ual v oi d s et Logger ( Logger Cont r ac t * l ogger ) =0; 10 v i r t ual Logger Cont r ac t * get Logger ( ) =0;

11 } ;

Gambar 3.19 Kode program classDeviceContract

Fungsi tersebut antara lain: fungsi turnOn, bertanggung jawab untuk logika menghidupkan perangkat; fungsi turnOff, bertanggung jawab untuk logika mematikan perangkat; fungsi behavior, adalah fungsi yang mengatur perilaku dari perangkat; fungsi initialize, adalah fungsi yang bertanggung jawab untuk inisialisasi perangkat; fungsi getPin, berfungsi untuk mendapatkan nomor pin perangkat dimana perangkat tersebut terhubung ke WemosD1; fungsi setLogger, adalah fungsi yang berguna untuk men-set Logger yang digunakan oleh perangkat; fungsi getLogger, adalah fungsi yang berguna untuk mendapatkan

Logger yang digunakan.

ClassDevice mempunyai beberapa properti seperti driver dan sensor. Properti driver merupakan sebuah instance dari class yang meng-extends class

DriverContract. Driver bertanggung jawab pada logika yang dibutuhkan untuk menghidupkan dan mematikan perangkat. Properti berikutnya adalah sensor yang berguna untuk mendapatkan nilai pembacaan tertentu, kemudian fungsi behavior dapat menggunakan nilai pembacaan tersebut untuk menjadi pertimbangan perilaku dari perangkat.


(50)

Instance dari classDevice tidak dapat langsung didaftarkan pada

ClassBoard. Hanya instance dari class yang meng-extends classDevice yang dapat didaftarkan pada classBoard. Anak class dari classDevice dapat berupa perangkat yang lebih spesifik seperti LED, lampu, remote A/C dan sebagainya.

3.5.6 SensorClass

SensorClassmerupakanclass yang memodelkan perangkat sensor yang terhubung ke WemosD1. Class ini memungkin proses pembacaan dapat dilakukan dengan lebih mudah. Class ini juga mempermudah mengaitkan sebuah sensor dengan sebuah perangkat, sehingga perangkat tersebut dapat mempunyai perilaku berdasarkan pada pembacaan sensor.

Class Sensor meng-extends class SensorContract dimana pada class

tersebut terdapat empat fungsi virtual yang harus diimplementasikan oleh class

Sensor. Fungsi tersebut antara lain: fungsi initialize, merupakan fungsi yang bertanggung jawab untuk melakukan inisialisasi sensor; fungsi readMeasurementValue, merupakan fungsi yang bertanggung jawab untuk mendapatkan nilai pembacaan sensor; fungsi setLogger, merupakan fungsi yang berguna untuk men-set object sensor yang digunakan; fungsi getLogger, merupakan fungsi yang berguna untuk mendapatkan Logger yang sedang digunakan. Class SensorContract untuk lebih jelasnya dapat dilihat pada Gambar 3.20.


(51)

1 c l as s Sens or Cont r ac t

2 { 3 publ i c:

4 v i r t ual v oi d i ni t i al i z e( ) =0;

5 v i r t ual doubl e r eadMeas ur ement Val ue( ) =0;

6 v i r t ual v oi d s et Logger ( Logger Cont r ac t * l ogger ) =0; 7 v i r t ual Logger Cont r ac t * get Logger ( ) =0;

8 } ;

Gambar 3.20 Kode program class SensorContract

3.5.7 LoggerClass

LoggerClassmerupakan sebuah class yang bertanggung jawab untuk mengumpulkan notifikasi perangkat dan pembacaan sensor yang terhubung ke

Wemos D1. ClassLogger meng-extends classLoggerContract yang berisi fungsi

virtual yang harus diimplementasikan oleh classLogger. ClassLoggerContract dapat dilihat pada Gambar 3.21.

1 c l as s Logger Cont r ac t

2 { 3 publ i c:

4 v i r t ual v oi d addNot i f i c at i on(i nt c ode, St r i ng mes s age) =0; 5 v i r t ual v oi d addSens or Meas ur ement (St r i ng s ens or Name, St r i ng __________meas ur ement Val ue) =0;

6 v i r t ual St r i ng get LogMes s age( ) =0; 7 v i r t ual v oi d pr i nt ToSer i al ( ) =0; 8 } ;

Gambar 3.21 Kode program classLoggerContract

Implementasi dari classLoggerContract yang dituliskan pada classLogger

pada dasarnya akan mengambil notifikasi pada setiap perangkat dan pembacaan pada setiap sensor dan menyatukan semua data tersebut menjadi sebuah teks dalam format JSON. Kemudian ClassGateway akan mengambil teks tersebut dan menggabungkannya dengan teks alamat server, publish key, subscribe key dan beberapa teks informasi uri lainnya menjadi sebuah alamat resources locator.


(52)

Setelah itu classGateway akan melakukan http get ke server menggunakan uri tersebut.

3.5.8 GatewayClass

GatewayClassmerupakanclass yang memodelkan modul Wi-Fi yang ada pada Wemos D1. Class ini memungkinkan proses melakukan http request menjadi lebih mudah. Pengaturan Wi-Fi seperti SSID, password, alamat IP, Subnet,

Gateway dan DNS dengan class ini juga menjadi lebih mudah karena sebuah file

configurasi khusus telah disiapkan untuk pengaturan classGateway ini seperti yang dapat dilihat pada Gambar 3.22.

1 names pac e env { 2

3 names pac e wi f i {

4 St r i ng s s i d = " Fugue2"; 5 St r i ng pas s wor d = " s ec r et "; 6 I PAddr es s i p(192, 168, 137, 69) ; 7 I PAddr es s s ubnet(255, 255, 255, 0) ; 8 I PAddr es s gat eway(192, 168, 137, 1) ; 9 I PAddr es s dns 1(8, 8, 8, 8) ;

10 I PAddr es s dns 2(8, 8, 4, 4) ; 11 }

12 13 }

Gambar 3.22 kode configurasi Wi-Fi

Kemudian untuk menggunakan nilai – nilai tersebut pada konfigurasi Wi-Fi dapat dilakukan dengan menggunakan syntax seperti yang terlihat pada Gambar 3.23

1 Wi Fi .c onf i g( env : : wi f i : : i p, env : : wi f i : : gat eway ,

2 env : : wi f i : : s ubnet , env : : wi f i : : dns 1, env : : wi f i : : dns 2) ;


(53)

Reques HTTP dapat dilakukan dengan menggunakan class khusus yang meng-extends classGatewayContract. Class ini mempunyai fungsionalitas konfigurasi seperti yang dijelaskan sebelumnya. Class ini dibagi menjadi dua, yaitu class HTTPClient yang menggunakan koneksi HTTP Persistent dan dan

class HTTPClient yang menggunakan koneksi HTTP Non-persistent. Koneksi HTTP persistent dapat dilakukan dengan memberikan kode “keep-alive” pada

header yang dikirimkan ke server seperti yang ditunjukkan Gambar 3.24. 1 i f( _r eus e) {

2 header += F(" k eep- al i v e") ; / / per s i s t ent 3 } el s e {

4 header += F(" c l os e") ; / / non- per s i s t ent 5 }

Gambar 3.24Pengaturan koneksi persistent dan non-persistent

ClassGateway juga bertanggung jawab untuk mengirimkan data ke server

dan menerima perintah dari server. Hal itu dapat dilakukan dengan melakukan HTTP get ke server dengan menggunakan uri yang terdiri dari beberapa sub-bagian seperti: mode, merupakan Mode yang digunakan, dalam hal ini mode yang digunakan adalah publish; Publish Key dan Subscribe Key, merupakan string acak sepanjang 42 karakter yang berguna untuk melindungi uri dari akses yang tidak diinginkan; signature, merupakan parameter tambahan yang berguna untuk memberikan tanda khusus dari data yang dikirimkan; Channel Name, merupakan nama kanal yang digunakan untuk berkomunikasi dengan server; Callback, merupakan fungsi yang akan dipanggil (dibagian server) setelah data diterima. Parameter – parameter tersebut juga dapat diatur melalui file config seperti pada Gambar 3.25.


(54)

1 names pac e env { 2

3 names pac e ht t pCl i ent {

4 St r i ng hos t = " www. wahy unugr aha. c om"; 5 St r i ng mode = " publ i s h";

6 St r i ng publ i s hKey = " pub- w- 3e5de365- 5d57- 48c 7- a317- 366ef 2846eb4";

7 St r i ng s ubs c r i beKey = " s ub- n- c c a59b64- d972- 11e5- bdd5 -_______________02ee2ddab7f e";

8 St r i ng s i gnat ur e = " 0";

9 St r i ng c hannel Name = " r umah1"; 10 St r i ng c al l bac k = " 0";

11 } 12 13 }

Gambar 3.25 Kode konfigurasi uri yang akan di-request oleh Wemos D1

3.6 Rancangan Aplikasi Web

Aplikasi untuk sistem Home Automation yang dirancang dibangun menggunakan bahasa PHP pada bagian back-end (server). Pada bagian front-end (UserInterface) digunakan Javascript dan HTML.

Aplikasi web yang dirancang menggunakan pola desain Model-View-Controller (MVC). Model yang dimaksud adalah model dari data yang disimpan di database. Model akan dimanipulasi oleh user menggunakan Controller, kemudian Model yang telah dimanipulasi akan meng-update View (UserInterface) yang akan dapat dilihat oleh pengguna. Pola MVC lebih jelasnya dapat dilihat pada Gambar 3.26.


(55)

Gambar 3.26 Desain Model-View-Controller 3.6.1 Back-end (Server)

Bagian server dari aplikasi web sistem Home Automation dibangun dengan menggunakan bahasa PHP. Sebuah framework PHP yang bernama Laravel digunakan untuk mempermudah proses pembuatan aplikasi web. Dengan Menggunakan framework Laravel penyimpanan data ke database tidak perlu menggunakan sintaks sql murni, namun hal ini telah diabstraksikan kedalam beberapa method dari class Model. Sehingga ketika untuk melakukan penyimpanyan data ke database cukup dilakukan dengan pemanggilan fungsi save.

3.6.1.1Routes

Pada aplikasi web yang dirancang terdapat beberapa route yang mengarah sebuah request ke Controller tertentu. Routeroute tersebut dapat dilihat pada Gambar 3.27.


(56)

1 <?php

2

3 Rout e: :get(' / ' , ' HomeCont r ol l er @i ndex ' ) ; 4 Rout e: :aut h( ) ;

_5_Rout e: :get(' publ i s h/ { publ i s hKey } / { s ubs c r i beKey } / { s i gnat ur e} { c hannel Name} / { c al l bac k } / { mes s age} ' ,

' Publ i s hCont r ol l er @handl e' ) ;

6 Rout e: :get(' manage/ das hboar d' , ' Das hboar dCont r ol l er @i ndex ' ) ; 7 Rout e: :get(' manage/ das hboar d/ c ons ol e' ,

' Cons ol eCont r ol l er @i ndex ' ) ; 8 Rout e: :get(' not i f i c at i ons ' ,

' Not i f i c at i ons Cont r ol l er @i ndex ' ) ;

9 Rout e: :get(' not i f i c at i ons / { not i f i c at i ons } / s een' ,

' Not i f i c at i ons Cont r ol l er @s een' ) ;

10 Rout e: :get(' meas ur ement s ', ' Meas ur ement s Cont r ol l er @i ndex ' ) ; 11 Rout e: :get(' meas ur ement s / { meas ur ement s } / s een' ,

' Meas ur ement s Cont r ol l er @s een' ) ;

12 Rout e: :get(' c ommands / 1/ { pi n} ' , ' Commands Cont r ol l er @t ur nOn' ) ; 13 Rout e: :get(' c ommands / 0/ { pi n} ' ,

' Commands Cont r ol l er @t ur nOf f ' ) ;

Gambar 3.27Routes yang digunakan di dalam aplikasi web

Route ‘/’ merupakan route untuk halaman awal. Misalnya ketika user

mengakses www.wahyunugraha.com maka route yang dikunjungi adalah route ‘/’ dan server akan meneksekusi fungsi index yang ada pada classHomeController.

Route ’auth’ merupakan route yang menangani login dan registeruser.

Route ini merupakan route bawaan framework Laravel. Route ini juga menyediakan halaman untuk melakukan login dan registrasi.

Route ‘manage’ merupakan sebuah route untuk halaman manajemen aplikasi web. Route ini mempunya dua sub-route yaitu ‘/dashBoard’ dan ‘dashBoard/console’. Route ‘/dashBoard’ akan menampilkan semua perangkat yang tersambung ke Wemos D1. Pada route ini juga ditampilkan tombol kendali untuk menghidupkan atau mematikan perangkat yang tersambung ke Wemos D1. Pada routedashBoard/console’ akan ditampilkan sebuah console terminal yang menampilkan aktivitas dari sistem Home Automation.


(57)

Route ‘notification’ merupakan route yang berguna untuk mengambil seluruh notifikasi yang belum dibaca dalam format JSON. Route ini mempunyai sebuah sub-route ‘notification/{notifications}/seen’ yang berfungsi untuk mendai suatu notifikasi sebagai notifikasi yang sudah dilihat.

Route ‘measurement’ merupkan route yang berguna untuk menampilkan seluruh nilai pembacaan sensor yang belum dilihat. Sama seperti route

notification, route ini juga mempunyai sebuah sub-route yang berfungsi untuk menandai sebuah measurement sebagai measurement yang telah dilihaat.

Routecommands’ merupakan route yang berfungsi untuk mengirimkan perintah ke WemosD1. Angka 1 atau 0 pada route ini menyatakan perintah apa yang akan dikirimkan, jika 1 maka perintah yang dikirimkan adalah perintah untuk menghidupkan perangkat dan jika 0 maka perintah yang dikirim adalah perintah untuk mematikan perangkat.

3.6.1.2 Migrations dan Model

Migration pada framework laravel adalah sebuah class yang menangi pembuatan table pada database. Pada aplikasi web sistem Home Automation yang dirancang terdapat 3 buah tabel database. Tabel tersebut yaitu: tabel commands, merupakan tempat dimana semua perintah dari penggunan akan disimpan sementara sebelum dikirim ke Wemos D1; tabel notifications, merupakan tabel yang menyimpan seluruh notifikasi yang datang dari Wemos D1; tabel

measurements, merupakan tabel yang menyimpan seluruh hasil pembacaan sensor yang terhubung ke Wemos D1.


(58)

Seluruh tabel yang dibuat di migrations kemudian dimodelkan kedalam

class Model. Class modul setiap tabel merupakan anak class dari Illuminate\Database\Eloquent\Model, dimana pada class tersebut terdapat banyak sekali fungsi – fungsi yang membantu pen-query-an data dari database atau penyimpanan data ke database.

3.6.1.3Controllers

Controller adalah class yang digunakan oleh user untuk memanipulasi Model. Pada aplikasi web yang dirancang terdapat tujuh buah Controller.

Controller tersebuat antara lain: CommandController, ConsoleController,

DashBoardController, HomeController, MeasurementsController,

NotificationsController, dan PublishController. Masing – masing Controller

tersebut mempunyai fungsi seperti yang dijelaskan pada bagian Routes.

3.6.2 Front-end (UserInterface)

Bagian userinterface dari applikasi web dibangun dengan menggunakan bahasa markup HTML dan Javascript. Aplikasi web yang dirancang terdiri dari 5 halaman, yaitu: landing page, halaman register, halaman login, halaman

dashBoard dan halaman console.

Landing page merupakan halaman awal yang akan dilihat oleh pengguna. Pada halaman ini pengguna bisa memilih aksi login atau register. Halaman ini diakses dari route ‘/’ dan dikontrol oleh classHomeController.

Halaman Register merupakan tempat dimana user mengisi data seperti nama, email, dan password untuk bergabung dengan sistem. Halaman ini diakses melalui route ‘auth’ dan dikontrol oleh class AuthController.


(59)

Halaman login merupakan tempat dimana pengguna memasukkan kredensialnya untuk masuk kedalam aplikasi web sistem Home Automation. Sama seperti halaman register, halaman ini juga diakses memalui route ‘auth’ dan dikontrol oleh class AuthController.

Halaman dashBoard merupakan halaman kendali utama. Pada halaman ini ditampilkan seluruh perangkat yang tersambung ke Wemos D1. Pada halaman ini juga ditampilkan tombol yang berfungsi untuk menghidupkan perangkat dan mematikan perangkat. Halaman ini diakses melalui route ‘manage/dashBoard’, serta dikontrol oleh classDashBoardController.

Halaman Console merupakan halaman yang dapat menampilkan aktivitas dari sistem Home Automation. Halaman ini diakses memalui route


(1)

3.2.5 Sensor Passive Infrared ... 29

3.2.6 Sensor Suhu ... 30

3.3 Cara kerja ... 31

3.4 Rancangan Bagian Hardware ... 34

3.5 Rancangan Software Controler ... 36

3.5.1 Controller Class ... 37

3.5.2 Collection Class ... 38

3.5.3 Scheduler Class... 40

3.5.4 Board Class... 42

3.5.5 Device Class ... 43

3.5.6 Sensor Class ... 45

3.5.7 Logger Class ... 46

3.5.8 Gateway Class ... 47

3.6 Rancangan Aplikasi Web ... 49

3.6.1 Back-end (Server) ... 50

3.6.2 Front-end (UserInterface) ... 53

BAB 4 HASIL DAN PEMBAHASAN... 55

4.1 Hasil Rancangan Model Sistem Home Automation ... 55

4.1.1 Kontroler ... 55

4.1.2 Aplikasi Web ... 57


(2)

vi

4.2 Analis Pengaruh Penggunaan Persistent dan Non-persistent HTTP ... 64

4.2.1 HTTP Persistent ... 65

4.2.2 HTTP Non-persistent ... 70

4.3 Pengukuran Jarak Maksimum Kontroler ke Hostspot ... 73

BAB 5 KESIMPULAN DAN SARAN ... 76

5.1 Kesimpulan ... 76

5.2 Saran ... 76

DAFTAR PUSTAKA ... 78

LAMPIRAN 1 KODE PROGRAM KONTROLER ... 79


(3)

DAFTAR GAMBAR

Gambar 2.1 Tiga layer utama sistem Home Automation ... 6

Gambar 2.2 Contoh sebuah sketch Arduino ... 7

Gambar 2.3 Board Wemos D1 ... 8

Gambar 2.4 Perbandingan arsitektur OSI dan TCP/IP. ... 9

Gambar 2.5 Proses enkapsulasi Data. ... 13

Gambar 2.6 Web servers dan web clients ... 18

Gambar 2.7 Pengunaan satu pernyataan use untuk meng-import beberapa class. 21 Gambar 2.8 Contoh penggunaan closure sebagai parameter ... 21

Gambar 2.9 Contoh kode javascript di dalam script HTML ... 22

Gambar 2.10 Struktuk sebuah program yang bersifat object-oriented. ... 24

Gambar 3.1 Gambaran umum sistem. ... 25

Gambar 3.2 Wemos D1 ... 27

Gambar 3.3 Modul relay empat kanal... 28

Gambar 3.4 Skematik modul relay empat kanal ... 28

Gambar 3.5 Hubungan paralel keempat lubang stop contact ... 29

Gambar 3.6 Sensor passive infrared... 29

Gambar 3.7 Sensor suhu DS18S20 ... 31

Gambar 3.8 Diagram alir sistem secara keseluruhan ... 32

Gambar 3.9 Modifikasi pengkabelan stop contact ... 34

Gambar 3.10 Keterhubungan perangkat – perangkat menjadi sistem Home Automation ... 35


(4)

viii

Gambar 3.12 Kode Program class BaseController ... 37

Gambar 3.13 Kode program classController ... 38

Gambar 3.14 Kode program classCollectionContract ... 38

Gambar 3.15 Kode program class koleksi Vector ... 39

Gambar 3.16 Kode program classScheduler ... 41

Gambar 3.17 Kode program class StaticEvent ... 42

Gambar 3.18 Kode program class Wemos D1... 43

Gambar 3.19 Kode program classDeviceContract ... 44

Gambar 3.20 Kode program class SensorContract ... 46

Gambar 3.21 Kode program classLoggerContract ... 46

Gambar 3.22 kode configurasi Wi-Fi... 47

Gambar 3.23 Setting Wi-Fi menggunakan nilai dari file konfigurasi ... 47

Gambar 3.24 Pengaturan koneksi persistent dan non-persistent ... 48

Gambar 3.25 Kode konfigurasi uri yang akan di-request oleh Wemos D1 ... 49

Gambar 3.26 Desain Model-View-Controller ... 50

Gambar 3.27 Routes yang digunakan di dalam aplikasi web ... 51

Gambar 4.1 Penampang komponen – komponen setelah dipasang diatas Board akrilik. ... 55

Gambar 4.2 Bentuk modifikasi stop contact ... 56

Gambar 4.3 Bentuk Stop contact yang terhubung ke relay ... 56

Gambar 4.4 Bentuk semua komponen yang telah dihubungkan ... 57

Gambar 4.5 Tampilan landing page... 58

Gambar 4.6 Tampilan halaman register... 59


(5)

Gambar 4.8 Tampilan halaman dashBoard ... 60 Gambar 4.9 Tampilan halaman console yang menampilkan notifikasi dari perangkat ... 61 Gambar 4.10 Kode program kontroler untuk melakukan ping ke server ... 62 Gambar 4.11 Hasil uji ping dari kontroler ke server ... 63 Gambar 4.12 Kode program class HTTP yang menggunakan koneksi persistent 65 Gambar 4.13 Script pengujian koneksi ... 66 Gambar 4.14 Isi data yang dimasukkan pada pesan request ... 66 Gambar 4.15 Isi dari pesan respon yang dikirimkan server ke Wemos D1 ... 67 Gambar 4.16 Grafik nilai waktu respon dengan menggunakan HTTP persistent 69 Gambar 4.17 Grafik nilai waktu respon dengan menggunakan HTTP non-persistent ... 72 Gambar 4.18 Perbandingan rata – rata waktu respon mengguanakan koneksi persistent dan non-persistent ... 73 Gambar 4.19 Grafik besar delay terhadap perubahan jarak ... 75


(6)

x DAFTAR TABEL

Tabel 2.1 Beberapa HTTP methods yang sering digunakan. ... 19 Tabel 3.1 Spesifikasi Wemos D1 ... 27 Tabel 3.2 Spesifikasi sensor PIR yang digunakan ... 30 Tabel 4.1 Waktu respon sistem Home Automation menggunakan koneksi HTTP persistent ... 67 Tabel 4.2 Waktu respon sistem Home Automation menggunakan koneksi HTTP non-persistent ... 71 Tabel 4.3 Hasil pengukuran delay dari Wemos D1 ke server berdasarkan jarak .. 74