GUI-O Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Episode 17: URL image stream

    Scheduled Pinned Locked Moved
    GUI-O Application Tutorial Series
    1
    1
    221
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • K
      kl3m3n
      last edited by kl3m3n

      This example shows how to obtain IP camera snapshots (via url request) and update image widget to produce continuous image stream.

      NOTE: GUI-O application v1.0.47 fixes image "flickering" bug.

      I will be using GUI-O Bluetooth Low Energy (LE) connection, but the example can be easily ported to other connection types.

      Software prerequisites:

      • Arduino IDE (https://www.arduino.cc/en/software)

      • ESP32 Arduino board support, if using ESP32 based board (see https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html)

      • GUI-O application (https://play.google.com/store/apps/details?id=com.guio.guioapp)

      • For additional information about the GUI-O application, download the developer manual from https://www.gui-o.com/

      Components needed:

      • ESP32-WROOM-32 (or any other Arduino supported Bluetooth Low Energy capable board)

      The entire tutorial is split into various steps. All necessary information is given in each step.

      0. DESIGN THE GUI (optional)

      The best way to create a GUI layout is to use GUI-O live designer tool. Please check previous episodes to see how to use the designer tool.

      1. UPLOAD THE SOURCE CODE

      The source code has inline comments, describing the important parts of the code. You can copy the source code from the snippet below, or download it here.

      Upload the code to your board (make sure that the correct board and upload port are selected). Reset the board after upload.

      /*
       * GUI-O Image Stream Bluetooth example (using ESP32-WROOM-32)
       *
       * Copyright (C) 2023, kl3m3n
       * last updated on 28.05.2023
       *
       * SPDX-License-Identifier: BSD-3-Clause
       */
      
      #include <BLEDevice.h>
      #include <BLEServer.h>
      #include <BLEUtils.h>
      #include <BLE2902.h>
      
      namespace uuid {
        static const char *SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
        static const char *RX_CHARACTERISTIC_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
        static const char *TX_CHARACTERISTIC_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
      } // namespace uuid
      
      // forward declare parser for incoming messages
      void parseGuioMsg(const String &msg);
      
      // setup done flag
      bool setupDone = false;
      
      // custom handling of server callbacks
      class CustomBLEServerCallbacks: public BLEServerCallbacks {
          void onConnect(BLEServer* pServer) {
            Serial.println("Connected!");
          };
          void onDisconnect(BLEServer* pServer) {
            Serial.println("Disconnected!");
            
            // restart advertising after disconnect, otherwise GUI-O cannot re-connect
            if(setupDone) {
              // restart advertising on disconnect
              delay(500);
              pServer->startAdvertising(); 
            }
          }
      };
      
      // custom handling of characteristic callbacks
      class CustomBLECharacteristicCallbacks: public BLECharacteristicCallbacks {
        void onWrite(BLECharacteristic *pCharacteristic) {
          std::string msg = pCharacteristic->getValue();
          
          // parse message string
          parseGuioMsg(String(msg.c_str()));
        }      
      };
      
      // global ptr
      BLECharacteristic *pTxCharacteristic;
      
      bool stream;
      unsigned long startTimestampMsec, currentTimestampMsec;
      const unsigned long updateIntervalMsec = 1000; // milliseconds
      
      void setup() {
        // debug output
        Serial.begin(115200);
      
        // create device
        BLEDevice::init("ImageStream");
        // create server and register callback
        BLEServer *pServer = BLEDevice::createServer();
        pServer->setCallbacks(new CustomBLEServerCallbacks());
        // create service
        BLEService *pService = pServer->createService(uuid::SERVICE_UUID);
      
        // crate Tx characteristic and add descriptor
        pTxCharacteristic = pService->createCharacteristic(uuid::TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY);
        pTxCharacteristic->addDescriptor(new BLE2902());
        
        // crate Rx characteristic and register callback
        BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(uuid::RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
        pRxCharacteristic->setCallbacks(new CustomBLECharacteristicCallbacks());
      
        // start the service and start advertising
        pService->start();
        pServer->getAdvertising()->start();
      
        // setup done flag
        setupDone = true;
      }
      
      void loop() {
        currentTimestampMsec = millis();
        if(currentTimestampMsec - startTimestampMsec > updateIntervalMsec) {
          if(stream)
            sendMsg("@im IP:\"https://kamere.dars.si/kamere/Kozina/Dilce_2.jpg\"\r\n");
          // reset read interval
          startTimestampMsec = millis();
        }  
      }
      
      void sendMsg(const String &msg) {
        pTxCharacteristic->setValue(std::string(msg.c_str()));
        pTxCharacteristic->notify();
        delay(50);
      }
      
      void parseGuioMsg(const String &msg) {
        if(msg.startsWith("@init")) {
          Serial.println("GUI-O app is requesting INITIALIZATION!");
      
          // clear screen and set background
          sendMsg("@cls\r\n");
          sendMsg("@guis BGC:#FFFFFF\r\n");
          delay(100);
      
          // initialize GUI
          sendMsg("|LB UID:title X:50 Y:20 FSZ:4 FFA:\"font8\" TXT:\"Image<br>stream\"\r\n");
          sendMsg("|IM UID:im X:50 Y:50 W:80 FURL:1 IP:\"https://kamere.dars.si/kamere/Kozina/Dilce_2.jpg\"\r\n");
          sendMsg("|TG UID:tg X:50 Y:75 EN:1\r\n");
          sendMsg("|LB UID:details X:50 Y:90 FSZ:2 TXT:\"GUI-O image stream<br>demonstration by kl3m3n\"\r\n");
      
          // defaults to true (tg has property EN set to true)
          stream = true;
        }
        else if(msg.startsWith("@tg"))
          stream = (msg.indexOf("1") > 0);
      }
      

      2. ESTABLISH CONNECTION

      Open GUI-O application and press Add in the upper-right corner of the home screen. Tap on Bluetooth LE and search for devices (enable Bluetooth and Location services, if prompted). Tap on the "ImageStream" device and wait for successful connection (confirm device pairing if prompted).

      Close the settings menu and press the Initialize button (see image below) from the GUI-O application home screen.

      initialize_button.jpg

      3. THE RESULT

      Image below shows the result (screen capture) on my Android device after pressing the "Initialize" button. The image stream is enabled by default and can be disabled by tapping on the toggle widget.

      screen.jpg


      If you have any questions or run into any problems, please let me know!

      Best regards,
      kl3m3n

      1 Reply Last reply Reply Quote 0
      • First post
        Last post