robreuss / VirtualGameController

Software-based game controllers for iOS, tvOS, OS X and watchOS in Swift 4.2.
MIT License
462 stars 44 forks source link

Invalid Checksum #8

Closed PieterVO closed 8 years ago

PieterVO commented 8 years ago

Hi,

I get an invalid checksum error when I send a state of a custom element from the central to a peripheral. This is only the case when the CustomElementType = .String. Can you check if it's a general problem? So to be clear: I try to send some information (a string) from the central to a peripheral, so I'm trying to implement bidirectional communication.

Thanks

robreuss commented 8 years ago

Hi,

I just tested and was unable to reproduce. Test procedure below.

I generally only see the invalid checksum errors when sending large amounts of motion data on a less powerful device like an iPhone 4s - we're talking 100s of messages/sec - so it would be strange to see it when sending a small string. Are you sending small strings, large strings, or a fast stream of small strings?

Feel free to send more info about what you are attempting to do, as well as code if you like, and I'm happy to help getting it to work.

Rob

I tested this way:

        let keyboard = controller.elements.custom[CustomElementType.Keyboard.rawValue]!
        keyboard.value = "A string"
        controller.sendElementStateToPeripheral(keyboard)
        if let element: Element = VgcManager.elements.elementFromIdentifier(CustomElementType.Keyboard.rawValue) {

            element.valueChangedHandlerForPeripheral = { (element: Element) in

                print("Custom element handler fired for \(element.name) with value \(element.value)")

                self.peripheralControlPadView.flashView.backgroundColor = UIColor.brownColor()
                UIView.animateWithDuration(0.05, delay: 0.0, options: .CurveEaseIn, animations: {
                    self.peripheralControlPadView.flashView!.alpha = 1
                    }, completion: { finished in
                        self.peripheralControlPadView.flashView!.alpha = 0
                })

            }
        }
PieterVO commented 8 years ago

Hi,

Thank you for your help and excuse me if I'm writing some bad English.

I'm creating a card game. The Apple TV shuffles the deck of cards and then divide them among the players. I use a string to do this (each card has a number), with a delimiter (space).

Here the code I used to send the string value:

public func devide(){
    if (!hands.isEmpty){
        hands.removeAll()
    }
    self.deck = self.shuffleInPlace(deck)
    var temp = [Int]()
    for var i = 1;i < (deck.count+1);++i{
        temp.append(deck[i-1])
        if ((i%8 == 0)){
            hands.append(temp)
            temp.removeAll()
        }

    }

    //TODO check if right amount of controllers
    for controller in VgcController.controllers(){
        let playerI: Int = controller.playerIndex.rawValue
        if playerI > 0 {
            var str = ""
            str.appendContentsOf("\(hands[playerI-1][0])")
            for var i = 1; i < hands[playerI-1].count; ++i{
                str.appendContentsOf(" \(hands[playerI-1][i])")
            }
            let element: Element = controller.elements.custom[CustomElementType.Hand.rawValue]!
            element.value = str
            controller.sendElementStateToPeripheral(element)
        }
    }

    print("cards handed out")
}

The string is correctly generated, so don't worry about that.

The code I used for the handler (runs on an iPhone 5):

func createHandHandler(){
    //to check if cards are changed
    if let element: Element = VgcManager.elements.elementFromIdentifier(CustomElementType.Hand.rawValue) {

        element.valueChangedHandlerForPeripheral = { (element: Element) in

            print("Hand element handler fired for \(element.name) with value \(element.value)")
            self.game.updateHand(element)
        }

        print("created handler for Hand")

    }
}

Again, thank you for your help!

PieterVO commented 8 years ago

I've solved it for now. When I let the string begin with "hand", it doesn't give an invalid checksum error. So the final string I send looks like this then: "hand 1 2 3 4 5 6 7 8" I still doesn't get it to work with "1 2 3 4 5 6 7 8".

robreuss commented 8 years ago

Glad you got it working for you. Thanks to your examples of working and non-working strings, I was able to figure out the problem. It had to do with how the checksum was calculated for different data types. I was making an assumption that a String value would not be able to be cast into a Float, but since you sent along numbers, it exposed my flawed logic. I'm now handling Strings more explicitly. I'll be pushing the change out in the next day or so.

Note that you also have a Data (NSData) data type available for use. The idea behind that is that you would use NSKeyedArchive to archive your hand object and send that along to the Peripheral. It's a bit more complex, but will give you the ability to easily extend the information set that you are sending to the Peripheral

robreuss commented 8 years ago

I should note that I'm running 7.2 beta 3 - not sure if that makes a difference.

PieterVO commented 8 years ago

I'm using 7.2 beta 3 too.I will look to the Data option.Thank you for your help!