diff options
-rw-r--r-- | indi-celestronaux/auxproto.cpp | 71 | ||||
-rw-r--r-- | indi-celestronaux/auxproto.h | 18 | ||||
-rw-r--r-- | indi-celestronaux/celestronaux.cpp | 328 | ||||
-rw-r--r-- | indi-celestronaux/celestronaux.h | 24 |
4 files changed, 368 insertions, 73 deletions
diff --git a/indi-celestronaux/auxproto.cpp b/indi-celestronaux/auxproto.cpp index 0ba7a92..eca66a5 100644 --- a/indi-celestronaux/auxproto.cpp +++ b/indi-celestronaux/auxproto.cpp @@ -211,6 +211,32 @@ const char * AUXCommand::commandName(AUXCommands command) const return nullptr; } } + else if (m_Source == HEATER_17 || m_Destination == HEATER_17 || m_Source ==HEATER_BB || m_Destination==HEATER_BB) + { + switch (command) + { + case HEATER_GET_INPUT: + return "HEATER_GET_INPUT"; + case HEATER_GET_NPORTS: + return "HEATER_GET_NPORTS"; + case HEATER_GET_PORT_TYPE: + return "HEATER_GET_PORT_TYPE"; + case HEATER_GET_AMBIENT: + return "HEATER_GET_AMBIENT"; + case HEATER_SET_AGRESSIVENESS: + return "HEATER_SET_AGRESSIVENESS"; + case HEATER_SET_MANUAL: + return "HEATER_SET_MANUAL"; + case HEATER_GET_HEATER_STATUS: + return "HEATER_GET_HEATER_STATUS"; + case HEATER_SET_LED: + return "HEATER_SET_LED"; + case HEATER_GET_LED: + return "HEATER_GET_LED"; + default : + return nullptr; + } + } else { switch (command) @@ -416,54 +442,65 @@ unsigned char AUXCommand::checksum(AUXBuffer buf) return (unsigned char)(((~cs) + 1) & 0xFF); } +size_t AUXCommand::getDataSize(void) +{ + return m_Data.size(); +} + ///////////////////////////////////////////////////////////////////////////////////// /// Return 8, 16, or 24bit value as dictacted by the data response size. ///////////////////////////////////////////////////////////////////////////////////// -uint32_t AUXCommand::getData() +uint32_t AUXCommand::getData(size_t size, size_t offset) { - uint32_t value = 0; - switch (m_Data.size()) + uint32_t value=0; + if (!size) size=m_Data.size(); + switch (size) { + case 4: + value = (m_Data[offset] << 24) | (m_Data[offset+1] << 16) | (m_Data[offset+2] << 8) | m_Data[offset+3]; + break; + case 3: - value = (m_Data[0] << 16) | (m_Data[1] << 8) | m_Data[2]; + value = (m_Data[offset] << 16) | (m_Data[offset+1] << 8) | m_Data[offset+2]; break; case 2: - value = (m_Data[0] << 8) | m_Data[1]; + value = (m_Data[offset] << 8) | m_Data[offset+1]; break; case 1: - value = m_Data[0]; + value = m_Data[offset]; break; } return value; } + ///////////////////////////////////////////////////////////////////////////////////// /// Set encoder position in steps. ///////////////////////////////////////////////////////////////////////////////////// -void AUXCommand::setData(uint32_t value, uint8_t bytes) +void AUXCommand::setData(uint32_t value, uint8_t bytes,size_t offset) { - m_Data.resize(bytes); + m_Data.resize(bytes+offset); switch (bytes) { case 1: - len = 4; - m_Data[0] = static_cast<uint8_t>(value >> 0 & 0xff); + len = offset+4; + m_Data[offset] = static_cast<uint8_t>(value >> 0 & 0xff); break; case 2: - len = 5; - m_Data[1] = static_cast<uint8_t>(value >> 0 & 0xff); - m_Data[0] = static_cast<uint8_t>(value >> 8 & 0xff); + len = offset+5; + m_Data[offset + 1] = static_cast<uint8_t>(value >> 0 & 0xff); + m_Data[offset] = static_cast<uint8_t>(value >> 8 & 0xff); break; case 3: default: - len = 6; - m_Data[2] = static_cast<uint8_t>(value >> 0 & 0xff); - m_Data[1] = static_cast<uint8_t>(value >> 8 & 0xff); - m_Data[0] = static_cast<uint8_t>(value >> 16 & 0xff); + len = offset+6; + m_Data[offset + 2] = static_cast<uint8_t>(value >> 0 & 0xff); + m_Data[offset + 1] = static_cast<uint8_t>(value >> 8 & 0xff); + m_Data[offset] = static_cast<uint8_t>(value >> 16 & 0xff); break; } } diff --git a/indi-celestronaux/auxproto.h b/indi-celestronaux/auxproto.h index 3593eee..891a96c 100644 --- a/indi-celestronaux/auxproto.h +++ b/indi-celestronaux/auxproto.h @@ -60,7 +60,16 @@ enum AUXCommands GPS_GET_YEAR = 0x04, GPS_GET_TIME = 0x33, GPS_TIME_VALID = 0x36, - GPS_LINKED = 0x37 + GPS_LINKED = 0x37, + HEATER_GET_INPUT = 0x00, + HEATER_GET_NPORTS = 0x10, + HEATER_GET_PORT_TYPE = 0x11, + HEATER_GET_HEATER_STATUS = 0x12, + HEATER_SET_AGRESSIVENESS = 0x16, + HEATER_SET_MANUAL = 0x17, + HEATER_GET_AMBIENT = 0x18, + HEATER_SET_LED = 0x20, + HEATER_GET_LED = 0x21 }; enum AUXTargets @@ -71,11 +80,13 @@ enum AUXTargets HCP = 0x0d, AZM = 0x10, ALT = 0x11, + HEATER_17 = 0x17, APP = 0x20, GPS = 0xb0, WiFi = 0xb5, BAT = 0xb6, CHG = 0xb7, + HEATER_BB = 0xbb, LIGHT = 0xbf }; @@ -135,8 +146,9 @@ class AUXCommand * @param bytes How many bytes to interpret the data. * @return */ - uint32_t getData(); - void setData(uint32_t value, uint8_t bytes = 3); + uint32_t getData(size_t size=0, size_t offset=0); + size_t getDataSize(void); + void setData(uint32_t value, uint8_t bytes = 3,size_t offset=0); /////////////////////////////////////////////////////////////////////////////// /// Check sum diff --git a/indi-celestronaux/celestronaux.cpp b/indi-celestronaux/celestronaux.cpp index d0a1932..c922059 100644 --- a/indi-celestronaux/celestronaux.cpp +++ b/indi-celestronaux/celestronaux.cpp @@ -345,6 +345,8 @@ bool CelestronAUX::initProperties() FirmwareTP[FW_WiFi].fill("WiFi version", "", nullptr); FirmwareTP[FW_BAT].fill("Battery version", "", nullptr); FirmwareTP[FW_GPS].fill("GPS version", "", nullptr); + FirmwareTP[FW_HEATER17].fill("Heater 17 version", "", nullptr); + FirmwareTP[FW_HEATERBB].fill("Heater BB version", "", nullptr); FirmwareTP.fill(getDeviceName(), "Firmware Info", "Firmware Info", MOUNTINFO_TAB, IP_RO, 0, IPS_IDLE); // Gain Rate @@ -354,6 +356,48 @@ bool CelestronAUX::initProperties() ///////////////////////////////////////////////////////////////////////////////////// /// Initial Configuration ///////////////////////////////////////////////////////////////////////////////////// + // + // + // + + + HeaterPower[0].fill("HEATER_VOLTAGE", "Voltage", "%.3fV", 0, 65.555, 0, 0); + HeaterPower[1].fill("HEATER_CURRENT", "Current", "%.3fA", 0, 65.555, 0, 0); + HeaterPower.fill(getDeviceName(), "HEATER_POWER", "Heater Power", HEATER_TAB, IP_RO, 60, IPS_IDLE); + + Ambient[0].fill("AMBIENT_TEMP", "Temperature", "%.3fC", -100.0, 100.0, 0, 0); + Ambient[1].fill("AMBIENT_DEW", "Dew point", "%.3fC", -100.0, 100.0, 0, 0); + Ambient[2].fill("AMBIENT_HUMID", "Humidity", "%.f%%", 0, 100.0, 0, 0); + Ambient.fill(getDeviceName(), "AMBIENT", "Ambient Conditions", HEATER_TAB, IP_RO, 60, IPS_IDLE); + + int i; + for (i=0;i<N_HEATER_CHAN;++i) { + char buf1[32]; + char buf2[32]; + snprintf(buf1,sizeof(buf1),"HEATERPORTMODE%d",i+1); + snprintf(buf2,sizeof(buf2),"Port %d Mode",i+1); + HeaterPortMode[i][0].fill("AUTO","Automatic", ISS_OFF); + HeaterPortMode[i][1].fill("MANU","Manual", ISS_OFF); + HeaterPortMode[i].fill(getDeviceName(), buf1,buf2,HEATER_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + + snprintf(buf1,sizeof(buf1),"HEATERPORTCTRL%d",i+1); + snprintf(buf2,sizeof(buf2),"Port %d Control",i+1); + HeaterPortControl[i][0].fill("AGGR", "Aggressiveness", "%.f", 0.0, 10.0, 0, 0); + HeaterPortControl[i][1].fill("PCT", "Percent", "%.f", 0.0, 100.0, 0, 0); + HeaterPortControl[i].fill(getDeviceName(), buf1,buf2, HEATER_TAB, IP_RW, 60, IPS_IDLE); + + snprintf(buf1,sizeof(buf1),"HEATERPORTSTATE%d",i+1); + snprintf(buf2,sizeof(buf2),"Port %d State",i+1); + HeaterPortState[i][0].fill("POWER", "Power", "%.1fW", 0.0, 200.0, 0, 0); + HeaterPortState[i][1].fill("TEMP", "Temperature", "%.3f", -100.0, 100.0, 0, 0); + HeaterPortState[i].fill(getDeviceName(), buf1,buf2, HEATER_TAB, IP_RO, 60, IPS_IDLE); + + m_heater_auto[i]=true; + m_heater_aggr[i]=5; + m_heater_pct[i]=0; + } + + // Set Debug Information for AUX Commands AUXCommand::setDebugInfo(getDeviceName(), DBG_CAUX); @@ -472,8 +516,22 @@ bool CelestronAUX::updateProperties() FirmwareTP[FW_BAT].setText(fwText); formatVersionString(fwText, 10, m_GPSVersion); FirmwareTP[FW_GPS].setText(fwText); + formatVersionString(fwText, 10, m_Heater17Version); + FirmwareTP[FW_HEATER17].setText(fwText); + formatVersionString(fwText, 10, m_HeaterBBVersion); + FirmwareTP[FW_HEATERBB].setText(fwText); defineProperty(&FirmwareTP); + defineProperty(&HeaterPower); + defineProperty(&Ambient); + int i; + for (i=0;i<N_HEATER_CHAN;++i) { + defineProperty(&HeaterPortMode[i]); + defineProperty(&HeaterPortControl[i]); + defineProperty(&HeaterPortState[i]); + } + + if (InitPark()) { // If loading parking data is successful, we just set the default parking values. @@ -525,6 +583,14 @@ bool CelestronAUX::updateProperties() } deleteProperty(FirmwareTP.getName()); + deleteProperty(HeaterPower.getName()); + deleteProperty(Ambient.getName()); + int i; + for (i=0;i<N_HEATER_CHAN;++i) { + deleteProperty(HeaterPortMode[i].getName()); + deleteProperty(HeaterPortControl[i].getName()); + deleteProperty(HeaterPortState[i].getName()); + } } return true; @@ -689,6 +755,16 @@ bool CelestronAUX::ISNewNumber(const char *dev, const char *name, double values[ // Process Alignment Properties ProcessAlignmentNumberProperties(this, name, values, names, n); + + + int i; + for (i=0;i<N_HEATER_CHAN;++i) { + if (HeaterPortControl[i].isNameMatch(name) && (n==2)) { + m_heater_aggr[i]=values[0]; + m_heater_pct[i]=values[1]; + UpdateHeater(i); + } + } } return INDI::Telescope::ISNewNumber(dev, name, values, names, n); @@ -866,6 +942,15 @@ bool CelestronAUX::ISNewSwitch(const char *dev, const char *name, ISState *state return true; } + int i; + for (i=0;i<N_HEATER_CHAN;++i) { + if (HeaterPortMode[i].isNameMatch(name)) { + HeaterPortMode[i].update(states, names, n); + m_heater_auto[i] = (HeaterPortMode[i][0].s==ISS_ON); + UpdateHeater(i); + } + } + // Process alignment properties ProcessAlignmentSwitchProperties(this, name, states, names, n); @@ -1045,14 +1130,16 @@ IPState CelestronAUX::GuideSouth(uint32_t ms) IPState CelestronAUX::GuideEast(uint32_t ms) { int8_t rate = static_cast<int8_t>(GuideRateNP[AXIS_AZ].getValue() * 100); - guidePulse(AXIS_RA, ms, -rate); +// guidePulse(AXIS_RA, ms, -rate); + guidePulse(AXIS_RA, ms, rate); return IPS_OK; // IPS_BUSY; // JMM - my mount doesn't reply } IPState CelestronAUX::GuideWest(uint32_t ms) { int8_t rate = static_cast<int8_t>(GuideRateNP[AXIS_AZ].getValue() * 100); - guidePulse(AXIS_RA, ms, rate); +// guidePulse(AXIS_RA, ms, rate); + guidePulse(AXIS_RA, ms, -rate); return IPS_OK; // IPS_BUSY; // JMM - my mount doesn't reply } @@ -1147,6 +1234,29 @@ bool CelestronAUX::ReadScopeStatus() return false; } + { + static int rotary =0; + + switch (rotary) { + case 0: + case 1: + case 2: + case 3: + getHeaterPort(rotary); + rotary++; + break; + case 4: + getHeaterPower(); + rotary++; + break; + case 5: + getAmbient(); + rotary=0; + break; + } + } + + // Mount Alt-Az Coords if (MountTypeSP[ALTAZ].getState() == ISS_ON) { @@ -2427,6 +2537,65 @@ bool CelestronAUX::getEncoder(INDI_HO_AXIS axis) return true; } +bool CelestronAUX::getHeaterPower(void) +{ + AUXCommand command(HEATER_GET_INPUT, APP,HEATER_17); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + + +bool CelestronAUX::getAmbient(void) +{ + AUXCommand command(HEATER_GET_AMBIENT, APP,HEATER_17); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + + +bool CelestronAUX::getHeaterPort(unsigned p) +{ + AUXCommand command(HEATER_GET_HEATER_STATUS, APP,HEATER_17); + command.setData(p,1); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + + +bool CelestronAUX::setHeaterManual(unsigned p,unsigned n) +{ + AUXCommand command(HEATER_SET_MANUAL, APP,HEATER_17); + command.setData(p-1,1); + command.setData(n,1,1); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + + +bool CelestronAUX::setHeaterAuto(unsigned p,unsigned a) +{ + AUXCommand command(HEATER_SET_AGRESSIVENESS, APP,HEATER_17); + command.setData((p-1),1); + command.setData(a,1,1); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + + +void CelestronAUX::UpdateHeater(unsigned p) +{ + if (m_heater_auto[p]) + setHeaterAuto(p+1,(int) m_heater_aggr[p]); + else + setHeaterManual(p+1,(int) ((255./100.) * m_heater_pct[p])); +} + + ///////////////////////////////////////////////////////////////////////////////////// /// This is simple GPS emulation for HC. /// If HC asks for the GPS we reply with data from our GPS/Site info. @@ -2549,7 +2718,56 @@ bool CelestronAUX::processResponse(AUXCommand &m) // Avoid infinite loop by not responding to ourselves emulateGPS(m); } - else if (m.destination() == APP) + else if (m.destination() == APP) { + if (m.command()==GET_VER) { + uint8_t *verBuf = nullptr; + switch (m.source()) + { + case MB: + verBuf = m_MainBoardVersion; + break; + case ALT: + verBuf = m_AltitudeVersion; + break; + case AZM: + verBuf = m_AzimuthVersion; + break; + case HCP: + case HC: + verBuf = m_HCVersion; + break; + case BAT: + verBuf = m_BATVersion; + break; + case WiFi: + verBuf = m_WiFiVersion; + break; + case GPS: + verBuf = m_GPSVersion; + break; + case HEATER_17: + verBuf = m_Heater17Version; + break; + case HEATER_BB: + verBuf = m_HeaterBBVersion; + break; + case APP: + LOGF_DEBUG("Got echo of GET_VERSION from %s", m.moduleName(m.destination())); + break; + default: + break; + } + if (verBuf != nullptr) + { + size_t verBuflen = 4; + if ( verBuflen != m.dataSize()) + { + LOGF_DEBUG("Data and buffer size mismatch for GET_VER: buf[%d] vs data[%d]", verBuflen, m.dataSize()); + } + for (int i = 0; i < (int)std::min(verBuflen, m.dataSize()); i++) + verBuf[i] = m.data()[i]; + } + } else if (m.source() == AZM || m.source() == ALT) { switch (m.command()) { case MC_GET_POSITION: @@ -2640,63 +2858,71 @@ bool CelestronAUX::processResponse(AUXCommand &m) break; } break; + default: + break; + } + } else if (m.source() == HEATER_17 || m.source() == HEATER_BB) { + switch (m.command()) + { + case HEATER_GET_INPUT: + HeaterPower[0].setValue(0.001*m.getData(2,0)); + HeaterPower[1].setValue(0.001*m.getData(2,2)); + HeaterPower.setState(IPS_OK); + HeaterPower.apply(); + break; + case HEATER_GET_AMBIENT: + Ambient[0].setValue(0.001*m.getData(4,0)); + Ambient[1].setValue(0.001*m.getData(4,4)); + Ambient[2].setValue(m.getData(1,8)); + Ambient.setState(IPS_OK); + Ambient.apply(); + break; + case HEATER_GET_HEATER_STATUS: + { + int p=m.getData(1,0)-1; - case GET_VER: - { - uint8_t *verBuf = nullptr; - switch (m.source()) - { - case MB: - verBuf = m_MainBoardVersion; - break; - case ALT: - verBuf = m_AltitudeVersion; - break; - case AZM: - verBuf = m_AzimuthVersion; - break; - case HCP: - case HC: - verBuf = m_HCVersion; - break; - case BAT: - verBuf = m_BATVersion; - break; - case WiFi: - verBuf = m_WiFiVersion; - break; - case GPS: - verBuf = m_GPSVersion; - break; - case APP: - LOGF_DEBUG("Got echo of GET_VERSION from %s", m.moduleName(m.destination())); - break; - default: - break; - } - if (verBuf != nullptr) - { - size_t verBuflen = 4; - if ( verBuflen != m.dataSize()) - { - LOGF_DEBUG("Data and buffer size mismatch for GET_VER: buf[%d] vs data[%d]", verBuflen, m.dataSize()); - } - for (int i = 0; i < (int)std::min(verBuflen, m.dataSize()); i++) - verBuf[i] = m.data()[i]; +#if 0 + HeaterPortControl[0][1].setValue(p); + HeaterPortControl[0].apply(); + HeaterPortControl[0].setState(IPS_OK); + + break; +#endif + + if ((p<0) || (p>=N_HEATER_CHAN)) break; + + int mode=m.getData(1,1); + HeaterPortMode[p][0].setState(mode?ISS_ON:ISS_OFF); + HeaterPortMode[p][1].setState(mode?ISS_OFF:ISS_ON); + + HeaterPortControl[p][1].setValue((100./255.)*m.getData(1,2)); + HeaterPortState[p][0].setValue(0.1*m.getData(2,3)); + HeaterPortControl[p][0].setValue(m.getData(1,5)); + + if (m.getDataSize()==10) + HeaterPortState[p][1].setValue(0.001*m.getData(4,6)); + + HeaterPortMode[p].apply(); + HeaterPortMode[p].setState(IPS_OK); + HeaterPortState[p].apply(); + HeaterPortState[p].setState(IPS_OK); + HeaterPortControl[p].apply(); + HeaterPortControl[p].setState(IPS_OK); } - } - break; - default: - break; + break; + default: + break; } + } + + #if 0 // This turned out to be a stupid idea else if (m.destination() == 0xdd) { fwrite((const unsigned char *) (&m.data()[0]),m.dataSize(),1,stderr); } #endif - else - { + } else { DEBUGF(DBG_CAUX, "Got msg not for me (%s). Ignoring.", m.moduleName(m.destination())); } return true; diff --git a/indi-celestronaux/celestronaux.h b/indi-celestronaux/celestronaux.h index eb5c81d..ab39915 100644 --- a/indi-celestronaux/celestronaux.h +++ b/indi-celestronaux/celestronaux.h @@ -194,6 +194,11 @@ class CelestronAUX : bool getStatus(INDI_HO_AXIS axis); bool getEncoder(INDI_HO_AXIS axis); + bool getHeaterPower(void); + bool setHeaterManual(unsigned p,unsigned n); + bool setHeaterAuto(unsigned p,unsigned n); + bool getAmbient(void); + bool getHeaterPort(unsigned); ///////////////////////////////////////////////////////////////////////////////////// /// Coord Wrap @@ -244,6 +249,7 @@ class CelestronAUX : ///////////////////////////////////////////////////////////////////////////////////// bool guidePulse(INDI_EQ_AXIS axis, uint32_t ms, int8_t rate); + void UpdateHeater(unsigned); private: // Axis Information @@ -301,6 +307,8 @@ class CelestronAUX : uint8_t m_BATVersion[4] {0}; uint8_t m_WiFiVersion[4] {0}; uint8_t m_GPSVersion[4] {0}; + uint8_t m_Heater17Version[4] {0}; + uint8_t m_HeaterBBVersion[4] {0}; // Coord Wrap bool m_CordWrapActive {false}; @@ -336,8 +344,8 @@ class CelestronAUX : /////////////////////////////////////////////////////////////////////////////// // Firmware - INDI::PropertyText FirmwareTP {7}; - enum {FW_HC, FW_MB, FW_AZM, FW_ALT, FW_WiFi, FW_BAT, FW_GPS}; + INDI::PropertyText FirmwareTP {9}; + enum {FW_HC, FW_MB, FW_AZM, FW_ALT, FW_WiFi, FW_BAT, FW_GPS, FW_HEATER17, FW_HEATERBB}; // Mount type INDI::PropertySwitch MountTypeSP {2}; enum @@ -426,8 +434,19 @@ class CelestronAUX : RESET_TO_MARKS }; +#define N_HEATER_CHAN 4 + + INDI::PropertyNumber HeaterPower {2}; + INDI::PropertyNumber Ambient {3}; + INDI::PropertySwitch HeaterPortMode[N_HEATER_CHAN] {{2},{2},{2},{2}}; + INDI::PropertyNumber HeaterPortControl[N_HEATER_CHAN] {{2},{2},{2},{2}}; + INDI::PropertyNumber HeaterPortState[N_HEATER_CHAN] {{2},{2},{2},{2}}; private: + + bool m_heater_auto[N_HEATER_CHAN]; + float m_heater_aggr[N_HEATER_CHAN]; + float m_heater_pct[N_HEATER_CHAN]; // One definition rule (ODR) constants // AUX commands use 24bit integer as a representation of angle in units of @@ -454,6 +473,7 @@ class CelestronAUX : // Coord Wrap static constexpr const char *CORDWRAP_TAB {"Coord Wrap"}; static constexpr const char *MOUNTINFO_TAB {"Mount Info"}; + static constexpr const char *HEATER_TAB {"Heater"}; // Track modes static constexpr uint16_t AUX_SIDEREAL {0xffff}; static constexpr uint16_t AUX_SOLAR {0xfffe}; |