gopro / OpenGoPro

An open source interface specification to communicate with a GoPro camera with accompanying demos and tutorials.
https://gopro.github.io/OpenGoPro/
MIT License
708 stars 152 forks source link

Setting time on Hero12 #479

Open pavlosharhan2 opened 9 months ago

pavlosharhan2 commented 9 months ago

Leaving it here in case someone gets confused:

image

There is a bug in setting BLE command for hero12. The command works differently from Hero10. Setting utc time for hero 12 sets the local time. On hero10 it works as expected

tcamise-gpsw commented 6 months ago

Hello. I'm not exactly sure what you're saying here. Let's first clarify that there are 2 Set Date BLE API's:

  1. Set Date Time: does not take timezone and DST
  2. Set Local Date Time: does take timezone and DST

Set Local Date Time appears to work fine in that the datetime, timezone, and DST set from the command is reflected in the camera UI and successfully retrieved via the Get Date Time API's. Set Date Time also appears to work in that the datetime is reflected on the camera UI and successfully retrieved via the Get Date Time API's.

I see that the timezone remains unchanged when you use Set Date Time which is expected. However, I do see that the DST gets set to off if you had set it to on with Set Local Date Time. This is strange and I'm investigating this currently. Note that it should be a use case to mix these commands as you would normally only use one or the other. So if this does turn out to be a valid bug I will just document it as a known issue.

pavlosharhan2 commented 6 months ago

Set Local Date time may work correctly, I just don't use it because HERO10 doesn't support it.

What I'm saying is that in order to set the time via Set Date time i need to send local time if that's Hero11/Hero12 and UTC time if that's Hero10

This is my Kotlin function

@OptIn(ExperimentalUnsignedTypes::class)
    @RequiresPermission(allOf = ["android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT"])
    suspend fun setDateTimeOnGoPro(model: String) {
        DatadogLogger.i("Setting UTC date and time on GoPro")
        var utcDateTime: ZonedDateTime
        if(model=="HERO11+"){
            utcDateTime = ZonedDateTime.now()
        }
        else{//hero10
            utcDateTime = ZonedDateTime.now(ZoneOffset.UTC)
        }
        // Convert year to bytes
        val yearBytes = ByteBuffer.allocate(2).putShort(utcDateTime.year.toShort()).array()

        val dateTimeCmd = ubyteArrayOf(
            0x09U,  // Total number of bytes in the query
            0x0DU,  // Command ID for set date/time
            0x07U,
            yearBytes[0].toUByte(),                // First byte of year
            yearBytes[1].toUByte(),                // Second byte of year
            utcDateTime.monthValue.toUByte(),      // Month
            utcDateTime.dayOfMonth.toUByte(),      // Day
            utcDateTime.hour.toUByte(),            // Hour
            utcDateTime.minute.toUByte(),          // Minute
            utcDateTime.second.toUByte()           // Second
        )

        val connectedGoProBLEMac = DataStore.connectedGoProBLEMac
        if (connectedGoProBLEMac != null) {
            ble.writeCharacteristic(connectedGoProBLEMac, GoProUUID.CQ_COMMAND.uuid, dateTimeCmd)
        }
    }