Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the blinds drive like AM43 Blinds drive #576

Open
T-REX-XP opened this issue Mar 27, 2020 · 5 comments
Open

Add support for the blinds drive like AM43 Blinds drive #576

T-REX-XP opened this issue Mar 27, 2020 · 5 comments

Comments

@T-REX-XP
Copy link

Hi, it would be great, when the firmware will be extended by the support of AM43 Blinds drive.
Here is a few implementations of the controlling blinds via BLE:

Here is the device:
https://nl.aliexpress.com/item/4000025499519.html

@1technophile
Copy link
Owner

Nice idea!

@T-REX-XP
Copy link
Author

T-REX-XP commented Apr 18, 2020

Here is the BLE Arduino library,
I try to implement the control via sketch, the client already connected and find the characteristic, but I can't understand how I should send the packet in the correct format. can you help me with it??

Here are some of the packets from the worked project on none.js
Original sources: https://github.com/binsentsu/am43-ctrl/blob/master/src/am43.js

const AM43HANDLE = 0x000e;

const HEX_KEY_OPEN_BLINDS = "00ff00009a0d010096";
const HEX_KEY_CLOSE_BLINDS = "00ff00009a0d0164f2";
const HEX_KEY_STOP_BLINDS = "00ff00009a0a01cc5d";

const HEX_KEY_POSITION_BLINDS_PREFIX = "00ff0000";
const HEY_KEY_POSITION_BLIND_FIXED_CRC_CONTENT = "9a0d01";

const HEX_KEY_BATTERY_REQUEST = "00ff00009aa2010138";
const HEY_KEY_LIGHT_REQUEST = "00ff00009aaa010130";
const HEY_KEY_POSITION_REQUEST = "00ff00009aa701013d"; 

and here is the open blind function

    am43Open() {
        this.writeKey(AM43HANDLE, HEX_KEY_OPEN_BLINDS);
        this.lastaction = 'OPEN';
        this.state = 'OPEN';
    }


    writeKey(handle, key) {
        if (am43.busyDevice != null) {
            this.writeLog('Connection busy for other device, waiting...');
            setTimeout(() => {
                this.writeKey(handle, key)
            }, 1000);
            return;
        }

        this.performWriteKey(handle, key);
    }

@T-REX-XP
Copy link
Author

here is my sketch:

#include <Arduino.h>
/**
 * A BLE client example that is rich in capabilities.
 * There is a lot new capabilities implemented.
 * author unknown
 * updated by chegewara
 */

#include "BLEDevice.h"
//#include "BLEScan.h"
/*
const serviceUUID = '0000fe5000001000800000805f9b34fb';
const am43CharUUID = '0000fe5100001000800000805f9b34fb';
*/
// The remote service we wish to connect to.
//("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
static BLEUUID serviceUUID("0000fe50-0000-1000-8000-00805f9b34fb");

// The characteristic of the remote service we are interested in.
//("beb5483e-36e1-4688-b7f5-ea07361b26a8")
static BLEUUID charUUID("0000fe51-0000-1000-8000-00805f9b34fb");
//												   prefix(0x9a)-idOfAction(0x0d)(move)-len(data)-data(0x64)-checkSum(0xf2)
static uint8_t closeBlind[9] = {0x00, 0xff, 0x00, 0x00, 0x9a, 0x0d, 0x01, 0x64, 0xf2};

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic *pRemoteCharacteristic;
static BLEAdvertisedDevice *myDevice;

static void notifyCallback(
	BLERemoteCharacteristic *pBLERemoteCharacteristic,
	uint8_t *pData,
	size_t length,
	bool isNotify)
{
	Serial.print("Notify callback for characteristic ");
	Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
	Serial.print(" of data length ");
	Serial.println(length);
	Serial.print("data: ");
	Serial.println((char *)pData);
}

class MyClientCallback : public BLEClientCallbacks
{
	void onConnect(BLEClient *pclient)
	{
	}

	void onDisconnect(BLEClient *pclient)
	{
		connected = false;
		Serial.println("onDisconnect");
	}
};

bool connectToServer()
{
	Serial.print("Forming a connection to ");
	Serial.println(myDevice->getAddress().toString().c_str());

	BLEClient *pClient = BLEDevice::createClient();
	Serial.println(" - Created client");

	pClient->setClientCallbacks(new MyClientCallback());

	// Connect to the remove BLE Server.
	pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
	Serial.println(" - Connected to server");

	// Obtain a reference to the service we are after in the remote BLE server.
	BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
	if (pRemoteService == nullptr)
	{
		Serial.print("Failed to find our service UUID: ");
		Serial.println(serviceUUID.toString().c_str());
		pClient->disconnect();
		return false;
	}
	Serial.println(" - Found our service");

	// Obtain a reference to the characteristic in the service of the remote BLE server.
	pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
	if (pRemoteCharacteristic == nullptr)
	{
		Serial.print("Failed to find our characteristic UUID: ");
		Serial.println(charUUID.toString().c_str());
		pClient->disconnect();
		return false;
	}
	Serial.println(" - Found our characteristic");

	// Read the value of the characteristic.
	if (pRemoteCharacteristic->canRead())
	{
		std::string value = pRemoteCharacteristic->readValue();
		//uint8_t *valueRaw = pRemoteCharacteristic->readRawData();
		//Serial.print("The characteristic raw value was: ");
		//Serial.print(*valueRaw,HEX);

		/*byte byteArray[50];
		strcat( (char*)(&byteArray[0]),(char*)&value);
		Serial.print(byteArray[0],HEX);
		Serial.print(byteArray[1],HEX);
		

		*/
		//Serial.println((char*)&value);
		Serial.println("--The characteristic value was: ");
		
	}

	if (pRemoteCharacteristic->canNotify())
		pRemoteCharacteristic->registerForNotify(notifyCallback);

	connected = true;
}
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
	/**
   * Called for each advertising BLE server.
   */
	void onResult(BLEAdvertisedDevice advertisedDevice)
	{
		Serial.print("BLE Advertised Device found: ");
		Serial.println(advertisedDevice.toString().c_str());

		// We have found a device, let us now see if it contains the service we are looking for.
		if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID))
		{

			BLEDevice::getScan()->stop();
			myDevice = new BLEAdvertisedDevice(advertisedDevice);
			doConnect = true;
			doScan = true;

		} // Found our server
	}	  // onResult
};		  // MyAdvertisedDeviceCallbacks

void setup()
{
	Serial.begin(115200);
	Serial.println("Starting Arduino BLE Client application...");
	BLEDevice::init("");

	// Retrieve a Scanner and set the callback we want to use to be informed when we
	// have detected a new device.  Specify that we want active scanning and start the
	// scan to run for 5 seconds.
	BLEScan *pBLEScan = BLEDevice::getScan();
	pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
	pBLEScan->setInterval(1349);
	pBLEScan->setWindow(449);
	pBLEScan->setActiveScan(true);
	pBLEScan->start(5, false);
} // End of setup.

// This is the Arduino main loop function.
void loop()
{

	// If the flag "doConnect" is true then we have scanned for and found the desired
	// BLE Server with which we wish to connect.  Now we connect to it.  Once we are
	// connected we set the connected flag to be true.
	if (doConnect == true)
	{
		if (connectToServer())
		{
			Serial.println("We are now connected to the BLE Server.");
		}
		else
		{
			Serial.println("We have failed to connect to the server; there is nothin more we will do.");
		}
		doConnect = false;
	}

	    

	// If we are connected to a peer BLE Server, update the characteristic each time we are reached
	// with the current time since boot.
	if (connected)
	{
		//String newValue = "Time since boot: " + String(millis()/1000);
		Serial.println("Setting new characteristic value to Close blind code");	

		//String text ="Hello";
		uint8_t msg[6] ={0x9a}; //prefix 0x00, 0xff, 0x00, 0x00,
		msg[1] = 0x0d;  //  //move  // data // checksum
		msg[2] = 0x01; //{len(data)})
		msg[3] = 0x64; //data
		uint8_t checksum = 0;
		unsigned int index = 0; // Skip $ character at beginning
		const unsigned int length =sizeof(msg);
		for (; (index < length); ++index)
		{
			const char c = msg[index];
			if (c == '*')
				break;
			checksum = checksum ^ c;
		}
		msg[4] = checksum;

		Serial.println("XOR checksum of Hello:");
		Serial.print(checksum,HEX);
		//Serial.print(msg);

		// Set the characteristic's value to be the array of bytes that is actually a string.
		pRemoteCharacteristic->writeValue(closeBlind, true);
	}
	else if (doScan)
	{
		BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
	}

	delay(1000); // Delay a second between loops.
} // End of loop

@1technophile
Copy link
Owner

I started to implement a few month ago characteristic reading here for mi flora.
Maybe you could take it a look and see if it helps.

@kayaozalp
Copy link

There is a ESP32 library for AM43 here: https://github.com/buxtronix/am43

Would be great to combine it into OMG

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants