Skocz do zawartości

dab1994

Użytkownicy
  • Zawartość

    4
  • Rejestracja

  • Ostatnio

Reputacja

6 Neutralna

O dab1994

  • Ranga
    1/10

Informacje

Ostatnio na profilu byli

Blok z ostatnio odwiedzającymi jest wyłączony i nie jest wyświetlany innym użytkownikom.

  1. Zainspirowany artykułem o komunikacji Raspberry Pi z ESP32 z użyciem Mqqt chciałbym pokazać jak korzystając z JavaFx stworzyć prosty panel kontrolny dla urządzenia pracującego z tymże protokołem. JavaFX pozwala tworzyć aplikacje, które wyglądają bardziej nowocześnie, są równie wydajne, a przy tym można zachować dużo większą czytelność kodu. Od Javy w wersji 8 staje się to rekomendowaną biblioteką tworzenia graficznego interfejsu użytkownika[1]. Do przygotowania projektu będziemy potrzebować Eclipse IDE for Java Developers który znajdziemy tutaj https://www.eclipse.org/downloads/packages/ oraz wtyczki e(fx)clipse którą wyszukujemy i instalujemy poprzez Eclipse Marketplace znajdujący się w zakładce Help trzecia pozycja od dołu. Kiedy nasza instalacja zakończy się uruchamiamy ponownie Eclipsa i tworzymy nowy projekt wybierając File >> New >> Projekt… Po przejściu do ostatniego kroku kreatora nasz projekt pokaże się po lewej stronie. Do budowy projektu potrzebujemy jeszcze biblioteki Eclipse Paho którą znajdziemy pod tym odnośnikiem https://www.eclipse.org/downloads/download.php?file=/paho/releases/1.1.0/Java/plugins/org.eclipse.paho.client.mqttv3_1.1.0.jar Po pobraniu biblioteki dodajemy ją do naszego projektu przechodząc do File >> Properties I w zakładce Libraries w podmenu Java Builid Path wybieramy Add External JARs... i wskazujemy plik pobranej biblioteki. Teraz w naszym wygenerowanym projekcje ustawiamy parametry połączenia, kolejno nieprzechowywanie wiadomości pomiędzy ponownymi połączeniami z serwerem MQTT, czas oczekiwania na wiadomość, nazwę użytkownika i jego hasło. Na koniec tworzymy obiekt połączenia podając adres brokera wraz z portem oraz nazwę naszego klienta. MqttConnectOptions connectOptions = new MqttConnectOptions(); connectOptions.setCleanSession(true); connectOptions.setKeepAliveInterval(120); connectOptions.setUserName("tutaj nazwa użytkownika"); connectOptions.setPassword("tutaj hasło".toCharArray()); MqttClient mqttClient = new MqttClient("tcp://tutaj adres serwera:1883", "SimpleMqqt"); W następnym kroku stworzymy lewy panel który będzie wyświetlał stan czujników przykładowo temperaturę oraz obroty wentylatora oraz prawy panel z przyciskami do sterowania przykładowo oświetleniem zewnętrznym oraz oświetleniem wewnętrznym. Label temperatureLabel = new Label("Temperatura"); Label temperatureValue = new Label("0 \u2103"); Label fanLabel = new Label("Praca Wentylatora"); Label fanValue = new Label("0 %"); VBox leftBox = new VBox(temperatureLabel, temperatureValue, fanLabel, fanValue); leftBox.setAlignment(Pos.BASELINE_RIGHT); leftBox.setBackground(new Background(new BackgroundFill(Color.SEASHELL, null, null))); Label light1Label = new Label("Oświetlenie wnętrze"); Button light1Button = new Button("WYŁ"); Label light2Label = new Label("Oświetlenie zewnętrzne"); Button light2Button = new Button("WYŁ"); VBox rightBox = new VBox(light1Label, light1Button, light2Label, light2Button); rightBox.setAlignment(Pos.BASELINE_RIGHT); rightBox.setBackground(new Background(new BackgroundFill(Color.ALICEBLUE, null, null))); Mając już stworzone panele możemy dodać akcje dla przycisków czyli przesłanie wiadomości WŁ jeżeli przycisk na etykietę WYŁ i odwrotnie. Tutaj mam dwie możliwości tworząc obiekt wiadomości lub poprzez konfigurację bezpośrednią przy nadaniu wiadomości podając nazwę tematu, zawartość wiadomości, QoS, czy powinien zachować wiadomość light1Button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { //Wysłanie wiadomości bez tworzenia obiektu try { if (((Button) event.getSource()).getText().equals("WYŁ")) { mqttClient.publish("mqtt/control/light1", "WŁ".getBytes(), 0, false); } else { mqttClient.publish("mqtt/control/light1", "WYŁ".getBytes(), 0, false); } } catch (MqttException e) { e.printStackTrace(); } }}); light2Button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { //Wysłanie wiadomości z wykorzystaniem obiektu try { if (((Button) event.getSource()).getText().equals("WYŁ")) { MqttMessage mqttMessage = new MqttMessage(); mqttMessage.setPayload("WŁ".getBytes()); mqttMessage.setQos(0); mqttClient.publish("mqtt/control/light2",mqttMessage); } else { MqttMessage mqttMessage = new MqttMessage(); mqttMessage.setPayload("WYŁ".getBytes()); mqttMessage.setQos(0); mqttClient.publish("mqtt/control/light2", mqttMessage); } } catch (MqttException e) { e.printStackTrace(); } }}); Możemy sterować oświetleniem ale chcielibyśmy także otrzymywać aktualizację danych z czujników. W tym celu potrzebujemy stworzyć obiekt który pozwoli nam wykonać akcję po otrzymaniu nowej wiadomości. MqttCallback mqttCallback = new MqttCallback() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { if (topic.equals("mqtt/temperature")) { Platform.runLater(new Runnable() { @Override public void run() { temperatureValue.setText(message.toString() + " \u2103"); }}); } else if (topic.equals("mqtt/fan")) { Platform.runLater(new Runnable() { @Override public void run() { fanValue.setText(message.toString() + " %"); }}); } else if (topic.equals("mqtt/state/light1")) { Platform.runLater(new Runnable() { @Override public void run() { light1Button.setText(message.toString()); }}); } else if (topic.equals("mqtt/state/light2")){ Platform.runLater(new Runnable() { @Override public void run() { light2Button.setText(message.toString()); }}); }} @Override public void deliveryComplete(IMqttDeliveryToken arg0) { // TODO Auto-generated method stub } @Override public void connectionLost(Throwable arg0) { // TODO Auto-generated method stub } }; W metodzie messageArrived dodajemy akcje ustawienia wartości temperatury kiedy otrzymamy wiadomość dla tematu mqtt/temperature , tak samo dla pracy wentylatora oraz akcję zmiany etykiety przycisku sterowania oświetleniem kiedy w temacie mqtt/state/light pojawi zmiana jego stanu. Jako że budowa JavaFx nie pozwala bezpośrednio na zmianę wartości elementów musimy skorzystać z konstrukcji Platform.runLater. Tak przygotowany obiekt wskazujemy jako odbiorcę wiadomości w naszym obiekcie połączenia, łączymy się z brokerem za pomocą obiektu z parametrami połączenia oraz obserwujemy wybrane przez nas tematy. mqttClient.setCallback(mqttCallback); mqttClient.connect(connectOptions); mqttClient.subscribe("mqtt/temperature"); mqttClient.subscribe("mqtt/fan"); mqttClient.subscribe("mqtt/state/light1"); mqttClient.subscribe("mqtt/state/light2"); Do głównego okna aplikacji dodajemy poprzednio stworzone panele. BorderPane root = new BorderPane(); root.setLeft(leftBox); root.setCenter(rightBox); Scene scene = new Scene(root, 400, 400); scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); primaryStage.setScene(scene); primaryStage.setTitle("Simple Mqqt Control"); primaryStage.show(); Ostatni krok to dodanie akcji zamknięcia połączenia z naszym serwerem, kiedy zamkniemy okno naszej aplikacji. primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { @Override public void handle(WindowEvent event) { try { mqttClient.disconnect(); mqttClient.close(); } catch (MqttException e) { e.printStackTrace(); } } }); Nasz klient jest gotowy do użycia, jako że jest to tylko przykład nie powala swoim wyglądem. Jest podzielony na sekcję czujników i sekcję kontroli client.zip [1] https://javastart.pl/baza-wiedzy/frameworki/javafx
  2. Jeśli, chodzi o czujniki to sam pomysł jest taki żeby udostępniać odczyty z czujnika jako liczbę z dwoma miejscami po przecinku i w samej aplikacji tak samo wprowadzić nazwę, adres i jego numer, dodatkowo wybierając przy tym, czy mam być wyświetla w formacie liczbowym, czy procentowym. Nie mam pomysłu jak rozwiązać problem z przekaźnikami nie wiem, czy problem dotyczy przekaźników czy przycisków, po prostu stan żarówki zmienia się na przeciwny i tak zostaje, ale nie jest jakoś szczególnie uciążliwe.
  3. Dzień dobry, W swoim pierwszym wpisie, chciałbym przedstawić własną wersję sterownika światła sterowanego za pomocą aplikacji na androida. Sam sterownik składa się z: NodeMCU MODUŁ 2 PRZEKAŹNIKÓW 5V Dwóch przycisków Wspomagając się powyższym rysunkiem, zmontowałem całość korzystając z płytki uniwersalnej. NodeMCU łączy się z lokalną siecią WiFi. Do sterowania wykorzystuje bibliotekę aREST udostępniając funkcje on, off i get przyjmujące jako parametr numer przekaźnika. Kod w wersji skróconej i zdjęcia urządzenia do podejrzenia poniżej. // Rest and esp library #include <ESP8266WiFi.h> #include <aREST.h> // WiFi parameters const char* ssid = "ssid"; const char* password = "password"; const int SWITCH1 = 5; const int SWITCH2 = 16; const int RELAY1 = 12; const int RELAY2 = 14; const unsigned long INTERVAL = 500; bool relay1State = LOW; bool relay2State = LOW; bool switch1State = LOW; bool switch2State = LOW; unsigned long currentMillis = 0; unsigned long switch1Millis = 0; unsigned long switch2Millis = 0; aREST rest = aREST(); const int LISTEN_PORT = 80; WiFiServer server(LISTEN_PORT); int onControl(String value); int offControl(String value); int getControl(String value); void setup(void) { rest.set_id("10"); rest.set_name("Light Switches"); Serial.begin(115200); pinMode(SWITCH1, INPUT); pinMode(SWITCH2, INPUT); pinMode(RELAY1, OUTPUT); pinMode(RELAY2, OUTPUT); digitalWrite(RELAY1, !relay1State); digitalWrite(RELAY2, !relay2State); rest.variable("light1", &relay1State); rest.variable("light2", &relay2State); rest.function("on", onControl); rest.function("off", offControl); rest.function("get", getControl); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("Light Switches connected"); server.begin(); Serial.println("Light Switches address"); Serial.println(WiFi.localIP()); } void loop() { currentMillis = millis(); if (currentMillis - switch1Millis >= INTERVAL && digitalRead(SWITCH1)) { switch1State = !switch1State; if(switch1State==HIGH){ digitalWrite(RELAY1, LOW); relay1State = !LOW; } if(switch1State==LOW){ digitalWrite(RELAY1,HIGH ); relay1State = !HIGH; } switch1Millis = currentMillis; } if (currentMillis - switch2Millis >= INTERVAL && digitalRead(SWITCH2)) { switch2State = !switch2State; if(switch2State==HIGH){ digitalWrite(RELAY2, LOW); relay2State = !LOW; } if(switch2State==LOW){ digitalWrite(RELAY2,HIGH); relay2State = !HIGH; } switch2Millis = currentMillis; } WiFiClient client = server.available(); if (!client) { return; } while (!client.available()) { delay(10); } rest.handle(client); } int onControl(String value) { if (value=="0") { digitalWrite(RELAY1, LOW); relay1State = !LOW; switch1State = HIGH; return 0; } if (value=="1") { digitalWrite(RELAY2, LOW); relay2State = !LOW; switch2State = HIGH; return 0; } return -100; } int offControl(String value) { if (value=="0") { digitalWrite(RELAY1, HIGH); relay1State = !HIGH; switch1State = LOW; return 0; } if (value=="1") { digitalWrite(RELAY2, HIGH); relay2State = !HIGH; switch2State = LOW; return 0; } return -100; } int getControl(String value) { if (value=="0") { return relay1State; } if (value=="1") { return relay2State; } return -100; } Aplikacja składa się z czterech ekranów. Pierwszy to przełączanie żarówki przez przytrzymanie odpowiadającego jej pola na ekranie. Dwa kolejne odpowiadają za włącznie i wyłączenie wszystkich żarówek jednocześnie. Ostatni odpowiada za dodawanie i usuwanie połączeń, czyli wprowadzamy nazwę, adres urządzenia i numer przełącznika. Problemy i dalszy rozwój Jestem zadowolony z działania sterownika jedyny problem, jaki zaobserwowałem to przełączanie się przekaźników podczas podłączania innych urządzeń do przedłużacza, do którego jest wpięty. W aplikacji do bieżącej funkcjonalności chcę dodać włącznie wcześniej zdefiniowanych grup żarówek. I dodać nową funkcjonalności w postaci sterowania taśmami led, możliwość włączenia komputera, a także zakładkę gromadzącą wartości z czujników. Cały kod i aplikacja znajduje się w moim repozytorium
  4. Dzień dobry, Mam na imię Dawid. Hobbistycznie zajmuję się Arduino, którym zainteresowałem się właśnie dzięki kursom. Programuję w języku Java i rozwijam swoje umiejętności w programowaniu na Androida. W planach mam spróbowanie swoich sił w AVR.
×
×
  • Utwórz nowe...