mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2025-12-13 02:52:11 +01:00
* Moved shade storage from NVS. NVS storage became limited because of the wired ethernet boards. This limited the number of potential shades to around 20. * Added the ability to backup the shade configuration * Added the ability to restore the shade configuration. * Increased up. down, and tilt timing value to allow for up to 54 days of transition. The previous 16bit value did not allow for very slow shades and was limited to just over a minute. * UI cleanup and additional messages. * Transceiver tuning now applies the rx bandwidth in the proper order so no reboot is required.
267 lines
9.6 KiB
C++
267 lines
9.6 KiB
C++
#ifndef SOMFY_H
|
|
#define SOMFY_H
|
|
|
|
#define SOMFY_MAX_SHADES 32
|
|
#define SOMFY_MAX_LINKED_REMOTES 5
|
|
|
|
typedef struct appver_t {
|
|
uint8_t major;
|
|
uint8_t minor;
|
|
uint8_t build;
|
|
};
|
|
|
|
enum class somfy_commands : byte {
|
|
My = 0x1,
|
|
Up = 0x2,
|
|
MyUp = 0x3,
|
|
Down = 0x4,
|
|
MyDown = 0x5,
|
|
UpDown = 0x6,
|
|
Prog = 0x8,
|
|
SunFlag = 0x9,
|
|
Flag = 0xA
|
|
};
|
|
enum class shade_types : byte {
|
|
roller = 0x00,
|
|
blind = 0x01,
|
|
drapery = 0x02
|
|
};
|
|
|
|
String translateSomfyCommand(const somfy_commands cmd);
|
|
somfy_commands translateSomfyCommand(const String& string);
|
|
|
|
typedef struct somfy_frame_t {
|
|
bool valid = false;
|
|
bool processed = false;
|
|
int rssi = 0;
|
|
byte lqi = 0x0;
|
|
somfy_commands cmd;
|
|
uint32_t remoteAddress = 0;
|
|
uint16_t rollingCode = 0;
|
|
uint8_t encKey = 0xA7;
|
|
uint8_t checksum = 0;
|
|
uint8_t hwsync = 0;
|
|
uint8_t repeats = 0;
|
|
uint32_t await = 0;
|
|
void print();
|
|
void encodeFrame(byte *frame);
|
|
void decodeFrame(byte* frame);
|
|
bool isRepeat(somfy_frame_t &f);
|
|
void copy(somfy_frame_t &f);
|
|
};
|
|
|
|
class SomfyRemote {
|
|
// These sizes for the data have been
|
|
// confirmed. The address is actually 24bits
|
|
// and the rolling code is 16 bits.
|
|
protected:
|
|
char m_remotePrefId[10] = "";
|
|
uint32_t m_remoteAddress = 0;
|
|
public:
|
|
char *getRemotePrefId() {return m_remotePrefId;}
|
|
virtual bool toJSON(JsonObject &obj);
|
|
virtual void setRemoteAddress(uint32_t address);
|
|
virtual uint32_t getRemoteAddress();
|
|
virtual uint16_t getNextRollingCode();
|
|
virtual uint16_t setRollingCode(uint16_t code);
|
|
uint16_t lastRollingCode = 0;
|
|
virtual void sendCommand(somfy_commands cmd, uint8_t repeat = 1);
|
|
};
|
|
class SomfyLinkedRemote : public SomfyRemote {
|
|
public:
|
|
SomfyLinkedRemote();
|
|
};
|
|
class SomfyShade : public SomfyRemote {
|
|
protected:
|
|
uint8_t shadeId = 255;
|
|
uint64_t moveStart = 0;
|
|
uint64_t tiltStart = 0;
|
|
float startPos = 0.0;
|
|
float startTiltPos = 0.00;
|
|
bool seekingPos = false;
|
|
bool seekingTiltPos = false;
|
|
bool seekingMyPos = false;
|
|
bool settingMyPos = false;
|
|
uint32_t awaitMy = 0;
|
|
public:
|
|
shade_types shadeType = shade_types::roller;
|
|
bool hasTilt = false;
|
|
void load();
|
|
somfy_frame_t lastFrame;
|
|
float currentPos = 0.0;
|
|
float currentTiltPos = 0.0;
|
|
//uint16_t movement = 0;
|
|
int8_t direction = 0; // 0 = stopped, 1=down, -1=up.
|
|
int8_t tiltDirection = 0; // 0=stopped, 1=clockwise, -1=counter clockwise
|
|
uint8_t tiltPosition = 0;
|
|
uint8_t position = 0;
|
|
uint8_t target = 0;
|
|
uint8_t tiltTarget = 0;
|
|
uint8_t myPos = 255;
|
|
SomfyLinkedRemote linkedRemotes[SOMFY_MAX_LINKED_REMOTES];
|
|
bool paired = false;
|
|
bool fromJSON(JsonObject &obj);
|
|
bool toJSON(JsonObject &obj) override;
|
|
char name[21] = "";
|
|
void setShadeId(uint8_t id) { shadeId = id; }
|
|
uint8_t getShadeId() { return shadeId; }
|
|
uint32_t upTime = 10000;
|
|
uint32_t downTime = 10000;
|
|
uint32_t tiltTime = 7000;
|
|
bool save();
|
|
bool isIdle();
|
|
void checkMovement();
|
|
void processFrame(somfy_frame_t &frame, bool internal = false);
|
|
void setTiltMovement(int8_t dir);
|
|
void setMovement(int8_t dir);
|
|
void setTarget(uint8_t target);
|
|
void moveToTarget(uint8_t target);
|
|
void moveToTiltTarget(uint8_t target);
|
|
void sendTiltCommand(somfy_commands cmd);
|
|
void sendCommand(somfy_commands cmd, uint8_t repeat = 1);
|
|
bool linkRemote(uint32_t remoteAddress, uint16_t rollingCode = 0);
|
|
bool unlinkRemote(uint32_t remoteAddress);
|
|
void emitState(const char *evt = "shadeState");
|
|
void emitState(uint8_t num, const char *evt = "shadeState");
|
|
void setMyPosition(uint8_t target);
|
|
void moveToMyPosition();
|
|
void processWaitingFrame();
|
|
void publish();
|
|
void commit();
|
|
void commitShadePosition();
|
|
void commitTiltPosition();
|
|
void commitMyPosition();
|
|
};
|
|
|
|
typedef struct transceiver_config_t {
|
|
bool printBuffer = false;
|
|
bool enabled = false;
|
|
uint8_t type = 56; // 56 or 80 bit protocol.
|
|
uint8_t SCKPin = 18;
|
|
uint8_t TXPin = 12;
|
|
uint8_t RXPin = 13;
|
|
uint8_t MOSIPin = 23;
|
|
uint8_t MISOPin = 19;
|
|
uint8_t CSNPin = 5;
|
|
bool radioInit = false;
|
|
float frequency = 433.42; // Basic frequency
|
|
float deviation = 47.60; // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz.
|
|
float rxBandwidth = 812.5; // Receive bandwidth in kHz. Value from 58.03 to 812.50. Default is 99.97kHz.
|
|
int8_t txPower = 10; // Transmission power {-30, -20, -15, -10, -6, 0, 5, 7, 10, 11, 12}. Default is 12.
|
|
/*
|
|
bool internalCCMode = false; // Use internal transmission mode FIFO buffers.
|
|
byte modulationMode = 2; // Modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK.
|
|
uint8_t channel = 0; // The channel number from 0 to 255
|
|
float channelSpacing = 199.95; // Channel spacing in multiplied by the channel number and added to the base frequency in kHz. 25.39 to 405.45. Default 199.95
|
|
float dataRate = 99.97; // The data rate in kBaud. 0.02 to 1621.83 Default is 99.97.
|
|
uint8_t syncMode = 0; // 0=No preamble/sync,
|
|
// 1=16 sync word bits detected,
|
|
// 2=16/16 sync words bits detected.
|
|
// 3=30/32 sync word bits detected,
|
|
// 4=No preamble/sync carrier above threshold
|
|
// 5=15/16 + carrier above threshold.
|
|
// 6=16/16 + carrier-sense above threshold
|
|
// 7=0/32 + carrier-sense above threshold
|
|
uint16_t syncWordHigh = 211; // The sync word used to the sync mode.
|
|
uint16_t syncWordLow = 145; // The sync word used to the sync mode.
|
|
uint8_t addrCheckMode = 0; // 0=No address filtration
|
|
// 1=Check address without broadcast.
|
|
// 2=Address check with 0 as broadcast.
|
|
// 3=Address check with 0 or 255 as broadcast.
|
|
uint8_t checkAddr = 0; // Packet filter address depending on addrCheck settings.
|
|
bool dataWhitening = false; // Indicates whether data whitening should be applied.
|
|
uint8_t pktFormat = 0; // 0=Use FIFO buffers form RX and TX
|
|
// 1=Synchronous serial mode. RX on GDO0 and TX on either GDOx pins.
|
|
// 2=Random TX mode. Send data using PN9 generator.
|
|
// 3=Asynchronous serial mode. RX on GDO0 and TX on either GDOx pins.
|
|
uint8_t pktLengthMode = 0; // 0=Fixed packet length
|
|
// 1=Variable packet length
|
|
// 2=Infinite packet length
|
|
// 3=Reserved
|
|
uint8_t pktLength = 0; // Packet length
|
|
bool useCRC = false; // Indicates whether CRC is to be used.
|
|
bool autoFlushCRC = false; // Automatically flush RX FIFO when CRC fails. If more than one packet is in the buffer it too will be flushed.
|
|
bool disableDCFilter = false; // Digital blocking filter for demodulator. Only for data rates <= 250k.
|
|
bool enableManchester = true; // Enable/disable Manchester encoding.
|
|
bool enableFEC = false; // Enable/disable forward error correction.
|
|
uint8_t minPreambleBytes = 0; // The minimum number of preamble bytes to be transmitten.
|
|
// 0=2bytes
|
|
// 1=3bytes
|
|
// 2=4bytes
|
|
// 3=6bytes
|
|
// 4=8bytes
|
|
// 5=12bytes
|
|
// 6=16bytes
|
|
// 7=24bytes
|
|
uint8_t pqtThreshold = 0; // Preamble quality estimator threshold. The preable quality estimator increase an internal counter by one each time a bit is received that is different than the prevoius bit and
|
|
// decreases the bounter by 8 each time a bit is received that is the same as the lats bit. A threshold of 4 PQT for this counter is used to gate sync word detection.
|
|
// When PQT = 0 a sync word is always accepted.
|
|
bool appendStatus = false; // Appends the RSSI and LQI values to the TX packed as well as the CRC.
|
|
*/
|
|
void fromJSON(JsonObject& obj);
|
|
void toJSON(JsonObject& obj);
|
|
void save();
|
|
void load();
|
|
void apply();
|
|
void removeNVSKey(const char *key);
|
|
};
|
|
class Transceiver {
|
|
private:
|
|
static void handleReceive();
|
|
bool _received = false;
|
|
somfy_frame_t frame;
|
|
public:
|
|
transceiver_config_t config;
|
|
bool printBuffer = false;
|
|
bool toJSON(JsonObject& obj);
|
|
bool fromJSON(JsonObject& obj);
|
|
bool save();
|
|
bool begin();
|
|
void loop();
|
|
bool end();
|
|
bool receive();
|
|
void clearReceived();
|
|
void enableReceive();
|
|
void disableReceive();
|
|
somfy_frame_t& lastFrame();
|
|
void sendFrame(byte *frame, uint8_t sync);
|
|
void beginTransmit();
|
|
void endTransmit();
|
|
};
|
|
class SomfyShadeController {
|
|
protected:
|
|
uint8_t m_shadeIds[SOMFY_MAX_SHADES];
|
|
uint32_t lastCommit = 0;
|
|
public:
|
|
appver_t appVersion;
|
|
bool useNVS() { return !(this->appVersion.major > 1 || this->appVersion.minor >= 4); }
|
|
bool isDirty = false;
|
|
uint32_t startingAddress;
|
|
uint8_t getNextShadeId();
|
|
uint32_t getNextRemoteAddress(uint8_t shadeId);
|
|
SomfyShadeController();
|
|
Transceiver transceiver;
|
|
SomfyShade *addShade();
|
|
SomfyShade *addShade(JsonObject &obj);
|
|
bool deleteShade(uint8_t shadeId);
|
|
bool begin();
|
|
void loop();
|
|
void end();
|
|
SomfyShade shades[SOMFY_MAX_SHADES];
|
|
bool toJSON(DynamicJsonDocument &doc);
|
|
bool toJSON(JsonArray &arr);
|
|
bool toJSON(JsonObject &obj);
|
|
uint8_t shadeCount();
|
|
SomfyShade * getShadeById(uint8_t shadeId);
|
|
SomfyShade * findShadeByRemoteAddress(uint32_t address);
|
|
void sendFrame(somfy_frame_t &frame, uint8_t repeats = 0);
|
|
void processFrame(somfy_frame_t &frame, bool internal = false);
|
|
void emitState(uint8_t num = 255);
|
|
void publish();
|
|
void processWaitingFrame();
|
|
void commit();
|
|
bool loadShadesFile(const char *filename);
|
|
bool loadLegacy();
|
|
};
|
|
|
|
#endif
|