Difference between app and IDE simulator

I am new to ST and trying to learn how to write a device type for my ST shield. I have just been using the example code so far, but I have noticed that what I see in the IDE simulator is not also working in the ST app and I cannot understand why. In particular, the below code is supposed to show the messages sent from the arduino, running the On/Off shield example sketch, in the message value tile. It does in the IDE, however in the app on my phone it doesn’t work. All I see in that tile is “–”. Can anyone explain to me why that is the case?

Also, if anyone can point me to any additional references that break down the device type code I would really appreciate it. A lot of it is self explanatory, but there are some nuances I don’t really understand. Like when declaring a tile what does the device.*** actually do. And with the state, what does default do? And lastly, this may be due to my unfamiliarity with groovy, but how exactly does the syntax ${currentValue} work? I apologize for all the noobie questions and appreciate any advice you can throw my way. Thanks a lot!

 metadata {
	definition (name: "My Testing", author: "Nate") {
    		capability "Switch"
        	command "hello"
        	command "goodbye"
        	attribute "message","string"
	}

	tiles {
		standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true, canChangeBackground: true) {
            state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on"
			state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "off"
		}
		standardTile("greeting", "device.greeting", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
			state "default", label: 'hello', action: "hello", icon: "st.switches.switch.off", backgroundColor: "#ccccff"
		}     
		valueTile("message", "device.message", inactiveLabel: false) {
			state "default", label:'${currentValue}', unit:""
		}
        
		main "switch"
		details(["switch","greeting","message"])
	}
    simulator {
    }
}

def on() {
   log.debug "on"
   zigbee.smartShield(text: "on").format()
}

def off() {
	log.debug "on"
	zigbee.smartShield(text: "off").format()
}

def hello() {
	log.debug "Hello World!"
	zigbee.smartShield(text: "hello").format()
}

def goodbye() {
	log.debug "Bye Bye!"
	zigbee.smartShield(text: "goodbye").format()
}

def parse(String description) {
	log.debug "Parsing '${description}'"
	// TODO: handle 'switch' attribute
	// TODO: handle 'greeting' attribute
    def arduinoMsg = zigbee.parse(description)?.text //helper function returns original message from Arduino
    log.debug arduinoMsg
    sendEvent(name:"message", value:arduinoMsg)

}

I stumbled upon your post from 2 years ago. I have the same question. No one seems to have answered your post. There is a build in device with same name, which apparently work correctly. But do not know where the source code for that is.

Name of the device “On/Off shield example”