Giter Site home page Giter Site logo

Comments (20)

marklysze avatar marklysze commented on July 19, 2024 1

When your side is somewhat functional and I have time I'll run it and see if I can do my side to send and receive commands.

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Hi @gavalierm - it sounds like an interesting approach to working with the cameras - being able to separate the data and send it out instead of interpreting and processing it on the ESP32 sounds possible.

I think the Bluetooth connection would need to be maintained between the camera and the ESP32. I'm not familiar with passing connection handshakes, you probably know more about this than me.

I have limited time to work on my own project, unfortunately, as I'm working on another project. However, I am happy to try and help.

Working from my code base would be my preference (e.g. forked).

Are you planning on making the new project a public repository?

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

Hi @marklysze i m glad to hear that.

Yes it can be public, why not. But in fact, i tried to find this approach on github but i found nothing. So it looks like nobody needs this or nobody got this idea :) and how nobody use this public issue to create own bussines :)

Like i said i m not C programmer so i do not know how pointers work, why and how implement good and stable C code, if something works i do not know why really.

Because i use Arduino when it came out i m stuck on Arduino IDE and "arduino thinking" attitude. But i see that do not using Arduino wrappers build above the ESP IDF API is better idea, but i do not know how.

My project has simple idea (i sent to you a invitation to my private repo but i no think is still working.. 1yr old..) but need some better programmer..

The scenario is easy:
Phase A

  1. establish wifi
  2. establish mqtt (subscribe all topic what we need)
  3. start scanning for BT devices
  4. found and store devices with BM UUID match
  5. publish list to the mqtt
  6. if something match with last paired device establish connection (see phase B step 2) else stop

Phase B:

  1. after MQTT client see the list of cams... client send MQTT message to the ESP like "topic/epsid/connect" addr
  2. connect to the address
  3. camera respond with security event (only when unknown device tried to connect else skip to step 6)
  4. send MQTT message to MQTT client notify that the camera is on "wait for passcode" state
  5. client send MQTT message to ESP with passcode which will forward payload to the camera
  6. if al is OK connection is established - store address in "paired list"

Phase C:
Subscribe all bluetooth Services (ingoing, outgoing, camera state and so on..) and simply forward all payloads to the mqtt an vice versa
like MQTT topic like "topic/espid/tx" for sending and MQTT topic like "topic/espid/rx" fo receiving

All payloads are now forwarded and managed MQTT client and you can parse payloads waymore easy via javascript/python/whatever without compiling and flashing ESP again and again when logic needs update.

And ofcourse you can build own PWA with better looking UI, you are not limited to BT range, ESP display/touch capability, because your ESP is now transef all data to the mqtt topics and you can sit on you laptop and control cameras over PWA in your browser using mqtt client.

PWA mqtt client <-> mqtt broker server <-> mqtt client on ESP <-> bridge logic on esp <-> BT client on ESP <-> Camera

Because ESP32-C3 and ESP32-S3 have BT/WIFI coexitence it can be done - but like i said i cant write clean ESP code which make sense and you it looks like you can. So i share this idea with you and hope you can do this (if you like the idea)

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Appreciate your detailed response and thoughts on an approach.

I have just watched a short video on MQTT to try and understand it :). Sounds like it could work.

I'm sure I'll have more questions to help establish feasibility. I'll ask a few, though I'll be honest that I'm a bit concerned that we can't both do the C++ programming, as there will be a bit involved and my time is, unfortunately, limited.

However, let me ask a few more questions to see if we can make something:

  1. Can you list half a dozen example payloads that would be sent from the ESP32 and another half a dozen that would be sent to the ESP32?
  2. Have you got any ESP32 WiFi code? It's not something I have implemented.
  3. What were the concerns with both BT ond WiFi on a single ESP32? Is this a known issue?
  4. Can you outline what parts you would work on?

If the goal is to take all of the camera specific code into a front end application that could work but from my experience to date, camera setting changes have to be very specific and having access to a number of different models would help. The physical cameras are needed for development. For example, I tried coding for on URSA Mini Pro G2 but the resolution changing wasn't working because I needed to knov whicm resolutions were full sensor and which were windowed - it wasn't as simple as just sending a resolution value to the camera. The issue with the BMD protocol is there is no reply to a packet sent so in doesn't tell you if something wrong. I just want to give this example because replicating what is being done in C++ in the front end will be required if it is handling all of the configuration.

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

In fact MQTT is not the case (which i tried to use this time), it can be Websocket (which i use a lot), ESP-NOW (i never used because need another ESP-NOW - TCP/IP bridge to comunicate with other non-ESP devices).

The BMD protocol you have mentioned in your readme.md https://documents.blackmagicdesign.com/DeveloperManuals/BlackmagicCameraControl.pdf
https://github.com/coral/blackmagic-camera-protocol/blob/main/PROTOCOL.json

Bluetooth messages is the same as SDI messages so example trigger autofocus on camera 4
4 4 0 0 0 1 0 0
In fact Bluetooth protocol ignore the "camera id" bit, because you communicate directly with the single one camera. So camera accept via Bluetooth every camera id (so im no worry about) and i want to keep as much logic as possible in javascript not in ESP, so i want to send data info ESP_ID topic and decide what data this ESP needs.

SDI protocol is "broadcast" so every single device catch the data and parse "device bit" and if match with their own use data, but this means that every ESP need to know what device id represents and this means more logic into ESP and more handshaking between ESP and Node.js to declare device id.

So easy way is do not wory about device_id in ESP - during MQTT handshaking determine the ESP_ID (this is constatn based on ESP mac addr, or cpu_id...) and use dynamic mapping in Node.js like "this cpu id = this SDI device ID".

And this can be managed fawlessly in some PWA.

So when you receive payload from BT is uint8_t *pData, size_t length, message which can be directly forward to the MQTT as "string"

I send data from MQTT to BT with this part of code: Message was like [4,6,0,0,4,2,128,1,0x33,0x01,0,0]

if(BT.isConnected()){
            //
            char* token = strtok(payload + 1, delimiter);  // + 1 Skip the first '[' character
            size_t i = 0;
            uint8_t* pData = new uint8_t[length];
            while (token != NULL && i < length - 1) {  // -1 Skip the last ']' character
                uint8_t value = 0;
                if (strncmp(token, "0x", 2) == 0) {  // Check if token starts with "0x"
                    value = static_cast<uint8_t>(strtoul(token + 2, NULL, 16));  // Convert token to hex value
                } else {
                    value = static_cast<uint8_t>(atoi(token));  // Convert token to decimal value
                }
                if(LOGGING) Serial.println(value);
                pData[i] = value;
                i++;
                token = strtok(NULL, delimiter);
                //value = =round(((range + 2047)/2048) * (2048 * P2))
            }

            BT.send(pData,i);
            // Free the dynamically allocated memory
            delete[] pData;
        }

and sendig message from BT to MQTT

static void receiveNotify(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
{

    if (length < 4) {
        // Invalid packet, ignore it
        return;
    }

    //skip group 9 is not documented and i do not know what it is
    if(pData[4] == 9){
        return;
    }
    //

    if(LOGGING) Serial.println("CONTROL: Publish change");

    char buffer[length * 4];
    int pos = 0;
    buffer[pos++] = '[';
    for (int i = 0; i < length; i++) {
      if (pData[i] == 0) {
        pos += sprintf(&buffer[pos], "0,");
      } else {
        pos += sprintf(&buffer[pos], "%d,", pData[i]);
      }
    }
    if (pos > 0) {
      buffer[pos - 1] = ']'; // Replace the last comma with null terminator
    }
    buffer[pos++] = '\0';

    //const char* str = reinterpret_cast<const char*>(pData);
    MQTT.publish(("btbm/" + tally_id + "/ccu/change").c_str(), 0, true, buffer);

}

And i plan write SDI protocol parser in javascript to use with for human needs... so when operator want to change isto to "400" i run

mqtt.send('topic',encodeDataToSDIProtocol('iso',400)); //return payload message for BT

and vice versa

mqtt.reveive('topic',decodeDataToSDIProtocol(payload_from_bt)); //return human readable data like "iso/400"

In recap:

  1. i can reverse enginnered all needed data and build the encoder/decoder with node.js (or or)
  2. i build my own tally system based on websocket broker for ATEM, via companion, via direct atem connection... so yes i write some wifi code, but like i said is dirty code with many globlal variables ..(but working like scharm for years)
  3. Yes i m concerned, but i had working code on my ESP32-C3 which work just fine the coexistence is something what ESP IDF have done by sharing RF time https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/coexist.html
  4. Is hard to say what i can do, because i cant write clean healty code in c (i m php developer with some node.js skills) but this is something what i need for my personal use so but i craft some ugly working code or ask somebody like you to help :)

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

And maybe i need to say that BT/WIFI coexistence was something that i can not trully tested.

It works like expected but sometimes i just randomly get ESP to reboot. And because i wasnt 100 percent sure that code is OK and Healthy i can not say that RF coexistence is bad idea OR just my code is rubbish with memory leaks...

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Okay, I understand better what you're thinking.

In the code base there's this class that handles incoming packets of data:
https://github.com/marklysze/Magic-Pocket-Control-ESP32/blob/main/src/CCU/CCUDecodingFunctions.cpp

So the ESP32 could send the bytes to the Websocket instead.

Similarly, there's a function in:
https://github.com/marklysze/Magic-Pocket-Control-ESP32/blob/main/src/Camera/BMDCameraConnection.cpp

Called sendBytesToOutgoing that will send bytes to the camera, so this could be called when receiving data from the Websocket.

It sounds like an interesting solution. If you can provide some sample code (whether it's yours or other code on GitHub) for ESP32 WiFi connect/maintain/disconnect, and ESP32 WebSocket then I can see how feasible it is to integrate into the code base. Then perhaps your repository could be the front end that accepts data and sends data back?

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

Wifi on ESP32 in arudino wrapper is very straightforward.

Still i will try to use MQTT not Websocket directly, and if this idea fails i rewrite it back to the websocket (which is more reasonable for bi-direct messaging)

If i use websocket i need to extend "SDI" protocol to some new/custom payloads like "bluetooth handshaking" and "heartbeats messaging" or even "tally signaling with custom colors" i m not familiar how SDI protocol separate the CCU and TALLY or others messages.

Here is my ino sketch for working ESP32 D1 mini tally light (based on websocket messages) - this is from my private repo

/*
 *
 *  Created on: 24.05.2015
 *
 */

#include <Arduino.h>
#include <EEPROM.h>

#include <ESP8266WiFi.h>
//#include <ArduinoJson.h>

#include <WebSocketsClient.h>

#include <Hash.h>

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// define the number of bytes you want to access
#define EEPROM_SIZE 1

#define SSID ""
#define PASS ""

#define HOST "atemrpi.local" //bridge service
#define PORT 9240 // Enter server port

#define USE_SERIAL Serial1

#define SW_1 16
#define SW_2 14
#define SW_3 12
#define SW_4 13

#define LED_PIN 0 //14;
#define NUMPIXELS 7 // Popular NeoPixel ring size

//ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;

Adafruit_NeoPixel pixels(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

bool tally_locked = false;

int luminance = 255; //at full

uint32_t black = pixels.Color(0, 0, 0);
uint32_t gray = pixels.Color(100, 80, 60);
uint32_t red = pixels.Color(255, 0, 0);
uint32_t green = pixels.Color(0, 255, 0);
uint32_t blue = pixels.Color(0, 0, 255);
uint32_t orange = pixels.Color(255, 100, 0);
uint32_t white = pixels.Color(255, 255, 255);
uint32_t violet = pixels.Color(255, 0, 250);
uint32_t pink = pixels.Color(255,190,200);
uint32_t yellow = pixels.Color(255, 200, 0);

int tally_id = 0;

bool io_status = false;
bool wifi_status = false;
bool atem_status = true; //not handled for now

int pgm = 0;
int pvw = 0;
int trs = 0;

uint32_t signal_color = black;
uint32_t tally_color = gray;

//
unsigned long interval=100;
// Tracks the time since last event fired
unsigned long previousMillis=0;
//
bool signal_state = false;
//

String hostname = "ESP Tally";

void doSignal(uint32_t color, int start_led = 0, int end_led = NUMPIXELS, float koef = 1){
  if( color == signal_color ){
    return;
  }
  USE_SERIAL.println("SIGNAL");
  //fill strip with same color from start to end, others pins stay untouched
  pixels.fill(black, 0, NUMPIXELS); //reset tp full black
  pixels.fill(color, start_led, end_led);
  //set luminance of whole strip // WARNING CAN BE LOSS by using lower value without reseting the color to the full bright
  pixels.setBrightness(luminance);
  //
  int lumi = round(luminance * koef);
  if( lumi < 50 ){
    lumi = 50;  
  }else if( lumi > 255 ){
    lumi = 255;  
  }
  //
  pixels.setBrightness(lumi);
  
  //send defined pattern to the led strip
  pixels.show(); 
  signal_color = color; //set last
}

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

	switch(type) {
    case WStype_ERROR:
      USE_SERIAL.printf("[WSc] Error!!!\n");
      break;
		case WStype_DISCONNECTED:
			USE_SERIAL.printf("[WSc] Disconnected!\n");
      io_status = false;
			break;
		case WStype_CONNECTED: {
			USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
      io_status = true;
      doSignal(white,0,1);
			// send message to server when Connected
      String message = "JOIN " + hostname;
			webSocket.sendTXT(message);
		}
			break;
		case WStype_TEXT:
			USE_SERIAL.printf("[WSc] get text: %s\n", payload);
      //String message = (char*)payload;
      parseMessage(payload);
			break;
		case WStype_BIN:
			USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
			//hexdump(payload, length);
			break;
    case WStype_PING:
      // pong will be send automatically
      //USE_SERIAL.printf("[WSc] get ping\n");
      break;
    case WStype_PONG:
      // answer to a ping we send
      //USE_SERIAL.printf("[WSc] get pong\n");
      break;
    default:
      USE_SERIAL.printf("[WSc] Default event\n");
      break;
    }

}

String converter(uint8_t *str){
    String message = String((char *)str);
    message.trim();
    return message;
}

void parseMessage( uint8_t * payload ){

  String message = converter(payload);

  int cmd_delimiter_index = message.indexOf(' ');
  //USE_SERIAL.println(cmd_delimiter_index);

  String cmd = "Test";

  if( cmd_delimiter_index > 1){
    cmd = message.substring(0,cmd_delimiter_index);
  }else{
    cmd = message;
  }

  //USE_SERIAL.println(cmd);
    if(cmd.equals("TALLY-LOCK")){
      String id = message.substring(cmd.length());
      if(id.toInt() == 1){
        tally_locked = true;
        tally_color = yellow;
      }else{
        tally_locked = false;
        tally_color = gray;
      }    
    }else if(cmd.equals("TALLY-PGM") || cmd.equals("TALLY-PVW")){
    String id = message.substring(cmd.length()); 
    //id = id.substring(0,id.indexOf(' '));
    USE_SERIAL.println(id);
    if(cmd.equals("TALLY-PGM")){
      trs = pgm;
      pgm = id.toInt();
    }
    if(cmd.equals("TALLY-PVW")){
      pvw = id.toInt();
    }

    if( pgm == tally_id ){
      tally_color = red;
    }else if( pvw == tally_id ){
      tally_color = green;
    }else{
      tally_color = gray;
    }

  }else if(cmd.equals("TALLY-TRS")){
    if( pgm == tally_id || pvw == tally_id || trs == tally_id){
      tally_color = red;
    }
  }else if(cmd.equals("SET-LUMINANCE")){
    String data = message.substring(cmd.length());
    luminance = data.toInt();
      if( luminance < 50 ){
        luminance = 50;  
      }else if( luminance > 255 ){
        luminance = 255;  
      }
      USE_SERIAL.println(luminance);
      pixels.setBrightness(luminance);
      pixels.show(); // light up
      EEPROM.write(0, luminance);
      EEPROM.commit();
  }
  
}
  
void setup() {
  pixels.begin(); // INITIALIZE NeoPixel pixel object (REQUIRED)

	USE_SERIAL.begin(115200); delay(500); //Waiting for serial

  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);

  // read the last LED state from flash memory
  if( EEPROM.read(0) > 5 ){
    luminance = EEPROM.read(0);
  }

  doSignal(white,0,1); //power on

	USE_SERIAL.setDebugOutput(true);

	USE_SERIAL.println();
	USE_SERIAL.println();
	USE_SERIAL.println();

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); //Powerpack keepalive internal led //this is not needed, becayse i dont use whole off (my black is single gray)

  pinMode(SW_1, INPUT_PULLUP); //NO INPUT_PULLUP on wemos D1 //PULLED hardway by 10k resistor
  pinMode(SW_2, INPUT_PULLUP);
  pinMode(SW_3, INPUT_PULLUP);
  pinMode(SW_4, INPUT_PULLUP);

  
  delay(1000); //human reaction to power on

  if( digitalRead(SW_1) == LOW ){
      tally_id += 1;
  }

  if( digitalRead(SW_2) == LOW ){
      tally_id += 2;
  }

  if( digitalRead(SW_3) == LOW ){
      tally_id += 3;
  }

  if( digitalRead(SW_4) == LOW ){
      tally_id += 4;
  }

  for (int i = 0; i < tally_id; ++i)
  {
    doSignal(red,0,1);
    delay(100);
    doSignal(black);
    delay(400);
  }

    USE_SERIAL.print( "TALLY ID: " ); USE_SERIAL.println( tally_id );
    //strcpy(watch_id, id.c_str());

    WiFi.mode(WIFI_STA); //SET STATION MODE // wifi simple client to avoid switching between modes
  
    //Get Default Hostname
    USE_SERIAL.printf("Default hostname: %s\n", WiFi.hostname().c_str());
  
    //Set new hostname
    hostname = WiFi.hostname() + "-" + tally_id;

    //String hostname = WiFi.hostname() + "-" + tally_id;
    WiFi.hostname(hostname);
  
    //Get Current Hostname
    USE_SERIAL.printf("New hostname: %s\n", WiFi.hostname().c_str());

	WiFi.begin(SSID, PASS);

	//WiFi.disconnect();
	while(WiFi.status() != WL_CONNECTED) {
    doSignal(blue,0,1);
    delay(100);
    doSignal(black);
    delay(400);
	}

	// server address, port and URL
	webSocket.begin(HOST, PORT, "/");

	// event handler
	webSocket.onEvent(webSocketEvent);

	// use HTTP Basic Authorization this is optional remove if not needed
	//webSocket.setAuthorization("user", "Password");

	// try ever 5000 again if connection has failed
	webSocket.setReconnectInterval(5000);
  
  // start heartbeat (optional)
  // ping server every 15000 ms
  // expect pong from server within 3000 ms
  // consider connection disconnected if pong is not received 2 times
  webSocket.enableHeartbeat(15000, 3000, 2);

}

void loop() {

  unsigned long currentMillis = millis();

	if(WiFi.status() == WL_CONNECTED) {
    webSocket.loop();
    wifi_status = true;
  } else {
    webSocket.disconnect();
    wifi_status = false;
  }

  if( wifi_status == false || io_status == false || atem_status == false ){
      uint32_t color = black;
      if( wifi_status == false ){
        color = blue;
      }else if( io_status == false ){
        color = orange;
      }else if( atem_status == false ){
        color = violet;
      }
    
       // How much time has passed, accounting for rollover with subtraction!
       if ((unsigned long)(currentMillis - previousMillis) >= interval) {
          // It's time to do something!
          //USE_SERIAL.println("Signal");
      if(signal_state){
        interval = 100;
          doSignal(black);
      }else{
        interval = 900;
          doSignal(color,0,1); //on
      }
          signal_state = !signal_state;
    
          // Use the snapshot to set track time until next event
          previousMillis = currentMillis;
       }
    
       //
      
      
    }else{
      // Get snapshot of time
      interval = 0;
      if( tally_color == gray ){
        interval = 50;
      }
      
      if(tally_locked){
        tally_color = yellow;
      }
       // How much time has passed, accounting for rollover with subtraction!
       if ((unsigned long)(currentMillis - previousMillis) >= interval) {
        USE_SERIAL.println("SIGNALING...");
          if( tally_color == gray ){
            doSignal(tally_color,0,1); //o
          }else if( tally_color == green ){
            doSignal(tally_color,1); //o
          }else{
            doSignal(tally_color); //o
          }
          previousMillis = currentMillis;
       }
    }
}

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Thanks for sharing that. Due to my time limitations, I'd suggest you start on your side of things and when you have some working code I'll try and tie in with it by sending camera commands through to you (the byte data) and taking command data I receive from you and send to the camera.

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

I can write some working code and add some notes like:
//TODO - send this data to camera here
//TODO - receive data from camera here

There is some limitations what i m thinikg about:

  • because on ESP32-C3 will run BLE/WIFI/MQTT libraries all libraries have to be light and as tiny as possible, all unanted code have to be removed or somehow skiped via "defines" (skip all libraries of serial, displays, ...)
  • because all idea is "event" driven maybe the Bluetooth part have to implement "onDataCallback" "sendDataCallback" "onPasscodeCallback" which can be asigned on setup()used in loop()
onDataCallback(mqtt, buffer_from_bt) {
    //called on BT onData event

    //sone validating stuff here
    //like inject destination byte, source byte
    //and send data
    mqtt.publish("topic", buffer_from_bt)
}

sendDataCallback(bt, buffer_from_mqtt) {
    //called on MQTT onData event
    switch buffer_from_mqtt[command_type_byte] {
        case: ENUMS.BT_PASSCODE_EVENT
        bt.setPasscode(buffer_from_mqtt)
        break;
        case: ENUMS.OTHER_NON_CCU_EVENT
        //do something differnet like store something in memory...
        //reboot
        //shatever
        break;
        return;
    }
    //sone validating stuff here
    //like inject destination byte, source byte
    //all other data are CCU and send data
    bt.writeCcuData(buffer_from_mqtt)
}

onPasscodeCallback(bt, buffer_from_mqtt) {
    //called on BT security/passcode event

    //sone validating studd here
    //like inject destination byte, source byte
    //notify that camera need passcode
    mqtt.publish("topic/passcode", null)
}

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

Maybe the good way is add fake BOARD like "ESP_mqtt" to your code context and implement for this board only callbacks without display stuff, if your code have this scalability.

And in main.c users define this board and will have access to the "mqtt bridge".

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

Data Block have data set to the max value

I m not sure thats 100 correct but i can update this when i found some mistakes.

This is auto generated from the data sheet.

https://github.com/gavalierm/blackmagic-camera-control-protocol

0 0 Lens Focus
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 00 80 00 00 08 00 00
0 1 Lens Instantaneous autofocus
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 00 01 00 00
0 2 Lens Aperture (f-stop)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 02 80 00 FF 7F 00 00
0 3 Lens Aperture (normalised)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 03 80 00 00 08 00 00
0 4 Lens Aperture (ordinal)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 04 02 00 00 01 00 00
0 5 Lens Instantaneous auto aperture
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 00 05 00 00
0 6 Lens Optical image stabilisation
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 00 06 00 00
0 7 Lens Set absolute zoom (mm)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 07 02 00 A0 0F 00 00
0 8 Lens Set absolute zoom (normalised)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 08 80 00 00 08 00 00
0 9 Lens Set continuous zoom (speed)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 00 09 80 00 00 08 00 00
1 0 Video Video mode
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 01 00 01 00
1 1 Video Gain (up to Camera 4.9)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 01 01 01 00 7F 00 00 00
1 2 Video Manual White Balance
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 01 02 02 00 32 32 00 00
1 3 Video Set auto WB
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 01 03 00 00
1 4 Video Restore auto WB
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 01 04 00 00
1 5 Video Exposure (us)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 01 05 03 00 10 A4 00 00
1 6 Video Exposure (ordinal)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 01 06 02 00
1 7 Video Dynamic Range Mode
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 01 07 01 00 02 00 00 00
1 8 Video Video sharpening level
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 01 08 01 00 03 00 00 00
1 9 Video Recording format
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 01 09 02 00
1 10 Video Set auto exposure mode
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 01 0A 01 00 04 00 00 00
1 11 Video Shutter angle
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 01 0B 03 00 A0 8C 00 00
1 12 Video Shutter speed
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 01 0C 03 00 88 13 00 00
1 13 Video Gain
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 01 0D 01 00 7F 00 00 00
1 14 Video ISO
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 01 0E 03 00 FF FF FF 7F
1 15 Video Display LUT
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 01 0F 01 00
1 16 Video ND Filter
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 01 10 80 00 FF 7F 00 00
2 0 Audio Mic level
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 02 00 80 00 00 08 00 00
2 1 Audio Headphone level
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 02 01 80 00 00 08 00 00
2 2 Audio Headphone program mix
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 02 02 80 00 00 08 00 00
2 3 Audio Speaker level
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 02 03 80 00 00 08 00 00
2 4 Audio Input type
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 02 04 01 00 03 00 00 00
2 5 Audio Input levels
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 02 05 80 00 00 00 08 00
2 6 Audio Phantom power
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 02 06 00 00
3 0 Output Overlay enables
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 03 00 00 00
3 1 Output Frame guides style (Camera 3.x)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 03 01 01 00 08 00 00 00
3 2 Output Frame guides opacity (Camera 3.x)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 03 02 80 00 00 08 00 00
3 3 Output Overlays (replaces .1 and .2 above from Cameras 4.0)
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 03 03 01 00 64 64 64 64
4 0 Display Brightness
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 04 00 80 00 00 08 00 00
4 1 Display Exposure and focus tools
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 04 01 00 00
4 2 Display Zebra level
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 04 02 80 00 00 08 00 00
4 3 Display Peaking level
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 04 03 80 00 00 08 00 00
4 4 Display Color bar enable
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 04 04 01 00 1E 00 00 00
4 5 Display Focus Assist
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 04 05 01 00
4 6 Display Program return feed enable
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 04 06 01 00 1E 00 00 00
5 0 Tally Tally brightness
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 05 00 80 00 00 08 00 00
5 1 Tally Front tally brightness
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 05 01 80 00 00 08 00 00
5 2 Tally Rear tally brightness
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 05 02 80 00 00 08 00 00
6 0 Reference Source
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 05 00 00 06 00 01 00 02 00 00 00
6 1 Reference Offset
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 06 01 03 00
7 0 Configuration Real Time Clock
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 07 00 03 00
7 1 Configuration System language
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 07 01 05 00
7 2 Configuration Timezone
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 07 02 03 00
7 3 Configuration Location
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 07 03 04 00
8 0 Color Correction Lift Adjust
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 0C 00 00 08 00 80 00 00 00 00 00 10 00 00 00
8 1 Color Correction Gamma Adjust
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 0C 00 00 08 01 80 00 00 00 00 00 20 00 00 00
8 2 Color Correction Gain Adjust
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 0C 00 00 08 02 80 00 FF FF FF FF 7F 00 00 00
8 3 Color Correction Offset Adjust
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 0C 00 00 08 03 80 00 00 00 00 00 40 00 00 00
8 4 Color Correction Contrast Adjust
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 08 04 80 00 00 00 10 00
8 5 Color Correction Luma mix
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 08 05 80 00 00 08 00 00
8 6 Color Correction Color Adjust
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 08 06 80 00 00 00 10 00
8 7 Color Correction Correction Reset Default
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 08 07 00 00
10 0 Media Codec
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0A 00 01 00
10 1 Media Transport mode
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0A 01 01 00
10 2 Media Playback Control
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0A 02 01 00
10 3 Media Still Capture
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0A 03 00 00
11 0 PTZ Control Pan/Tilt Velocity
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 08 00 00 0B 00 80 00 00 00 08 00
11 1 PTZ Control Memory Preset
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 0B 01 01 00 05 05 00 00
12 0 Metadata Reel
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 0C 00 02 00 E7 03 00 00
12 1 Metadata Scene Tags
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 01 01 00
12 2 Metadata Scene
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 02 05 00
12 3 Metadata Take
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 06 00 00 0C 03 01 00 63 63 00 00
12 4 Metadata Good Take
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 04 00 00
12 5 Metadata Camera ID
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 05 05 00
12 6 Metadata Camera Operator
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 06 05 00
12 7 Metadata Director
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 07 05 00
12 8 Metadata Project Name
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 08 05 00
12 9 Metadata Lens Type
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 09 05 00
12 10 Metadata Lens Iris
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 0A 05 00
12 11 Metadata Lens Focal Length
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 0B 05 00
12 12 Metadata Lens Distance
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 0C 05 00
12 13 Metadata Lens Filter
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 0D 05 00
12 14 Metadata Slate Mode
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 0C 0E 01 00
128 0 RGB Tally PGM
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 07 00 00 80 00 01 00 02 02 02 00
128 1 RGB Tally Set tally color
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 0C 00 00 80 01 02 00 FF FF FF FF 00 00 00 00
129 0 Bluetooth Disconnect
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 81 00 00 00
129 1 Bluetooth Connect
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 81 01 02 00
129 4 Bluetooth Passcode
De Le Cm __ Ca Pa Ty Op 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_
FF 04 00 00 81 04 03 00

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Maybe the good way is add fake BOARD like "ESP_mqtt" to your code context and implement for this board only callbacks without display stuff, if your code have this scalability.

And in main.c users define this board and will have access to the "mqtt bridge".

Yep, that's an idea - could add an MQTT specific board for platformio and in that main file could set parameters so that it uses MQTT instead of UI.

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

@marklysze

So i have some work done.

Disclaimer: Because i do not know if i m doing it right i do my best :)

What i choose:

  • i use ESP IDF (idf.py) for flashing and configuring the ESP32-S3
  • i use their native MQTT lib
  • i use nimble - the esp idf nimble stack

What i have done:

  • wifi, mqtt, signaling, some work on ble
  • i can connect to the camera
  • i can exchange the passkeys
  • i can bond device to do not ask passkey again

Interesting part:

  • i getting Timecode and CameraStatus notification (and data) - when i press timecode on camara ESP starts to log the time hex data (and its correct and for funny reason it have same structure as CCU protocol with group 9, which is skipped in CCU protocol.. :D )

Whan i m missing and what frustrate me

I think i was done BUT i realize that i can get any notification from CCU. I do not know WHY! because my subscribe is all the same as Timecode or CameraStatus.

I tried to write to the camera but without results (but this is not the case now, it was only one attempt)

I really missing something and i do not know what it is.

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

You've done a bit! Would you be able to point me to the code you've written?

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

I think i m fall in rabbit hole with Nimble ESP IDF. I think with basic Arduino BLE lib i will be done already....... I m struggling with basic i think in Nimble.

espressif/esp-idf#12989

My code is here https://github.com/gavalierm/btbm-tally and you have contributing rights, but because i rewrite whole code again and again becase testing and trying to get it done... maybe fork or branch will be good idea.

It is one big file main.c with included gatt_client.c to split thing. Because i do not get things done i do not need to keep code clean for now.

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Hey @gavalierm, gotcha - this does sometimes take us down paths that we weren't expecting!

I'll be honest that I'll find it hard to contribute to the repository because it's not in an environment I normally work in (VSCode and PlatformIO). If I do get some time to download it and load it I can see if I can get it going in VSCode/PlatformIO.

If there's any way you can run VSCode and PlatformIO with it I'd be able to help more...

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

I tried VScode many times, and still fallback to the my Sublime Text :)

Maybe sometime that PlatformIO will e standalone app like aruduino IDE. Or even better, somebody integrate the platform io to the Sublime text.

But meanwhile, ma code is done (all my headache) was described in the ESP-IDF issue.

If you wan to try my code you can, maybe it will stay public forever maybe not. But you will still have access as contributor.

Maybe you can help me check the syntex and resolve some "unprofessional" syntax? Like pointers, declarations or comparing and merging the data?

from magic-pocket-control-esp32.

gavalierm avatar gavalierm commented on July 19, 2024

You can try my code, it is working now.

from magic-pocket-control-esp32.

marklysze avatar marklysze commented on July 19, 2024

Cool, what device are you using?

from magic-pocket-control-esp32.

Related Issues (1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.