forked from Open-CT/openct-tasks
10495 lines
401 KiB
JavaScript
10495 lines
401 KiB
JavaScript
//"use strict";
|
||
var quickPiLocalLanguageStrings = {
|
||
fr: { // French strings
|
||
label: {
|
||
// Labels for the blocks
|
||
sleep: "attendre %1 millisecondes",
|
||
currentTime: "temps écoulé en millisecondes",
|
||
|
||
turnLedOn: "allumer la LED",
|
||
turnLedOff: "éteindre la LED",
|
||
|
||
setLedState: "passer la LED %1 à %2 ",
|
||
toggleLedState: "inverser la LED %1",
|
||
|
||
isLedOn: "LED allumée",
|
||
isLedOnWithName: "LED %1 allumée",
|
||
|
||
setLedBrightness: "mettre la luminosité de %1 à %2",
|
||
getLedBrightness: "lire la luminosité de %1",
|
||
|
||
turnBuzzerOn: "allumer le buzzer",
|
||
turnBuzzerOff: "éteindre le buzzer",
|
||
setBuzzerState: "mettre le buzzer %1 à %2",
|
||
isBuzzerOn: "buzzer allumé",
|
||
isBuzzerOnWithName: "buzzer %1 allumé",
|
||
|
||
setBuzzerNote: "jouer la fréquence %2Hz sur %1",
|
||
getBuzzerNote: "fréquence du buzzer %1",
|
||
|
||
isButtonPressed: "bouton enfoncé",
|
||
isButtonPressedWithName: "bouton %1 enfoncé",
|
||
waitForButton: "attendre une pression sur le bouton",
|
||
buttonWasPressed: "le bouton a été enfoncé",
|
||
|
||
displayText: "afficher %1",
|
||
displayText2Lines: "afficher Ligne 1 : %1 Ligne 2 : %2",
|
||
|
||
readTemperature: "température ambiante",
|
||
getTemperatureFromCloud: "temperature de la ville %1",
|
||
|
||
readRotaryAngle: "état du potentiomètre %1",
|
||
readDistance: "distance mesurée par %1",
|
||
readLightIntensity: "intensité lumineuse",
|
||
readHumidity: "humidité ambiante",
|
||
|
||
setServoAngle: "mettre le servo %1 à l'angle %2",
|
||
getServoAngle: "angle du servo %1",
|
||
|
||
|
||
drawPoint: "dessiner un pixel en x₀: %1 y₀: %2",
|
||
isPointSet: "pixel affiché en x₀: %1 y₀: %2",
|
||
drawLine: "ligne x₀: %1 y₀: %2 x₁: %3 y₁: %4",
|
||
drawRectangle: "rectangle x₀: %1 y₀: %2 largeur₀: %3 hauteur₀: %4",
|
||
drawCircle: "cercle x₀: %1 y₀: %2 diamètre₀: %3",
|
||
clearScreen: "effacer tout l'écran",
|
||
updateScreen: "mettre à jour l'écran",
|
||
autoUpdate: "mode de mise à jour automatique de l'écran",
|
||
|
||
fill: "mettre la couleur de remplissage à %1",
|
||
noFill: "ne pas remplir les formes",
|
||
stroke: "mettre la couleur de tracé à %1",
|
||
noStroke: "ne pas dessiner les contours",
|
||
|
||
readAcceleration: "accélération en (m/s²) dans l'axe %1",
|
||
computeRotation: "calcul de l'angle de rotation (°) sur l'accéléromètre %1",
|
||
readSoundLevel: "volume sonore",
|
||
|
||
readMagneticForce: "champ magnétique (µT) sur %1",
|
||
computeCompassHeading: "direction de la boussole en (°)",
|
||
|
||
readInfraredState: "infrarouge détecté sur %1",
|
||
setInfraredState: "mettre l'émetteur infrarouge %1 à %2",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "vitesse angulaire (°/s) du gyroscope %1",
|
||
setGyroZeroAngle: "initialiser le gyroscope à l'état zéro",
|
||
computeRotationGyro: "calculer la rotation du gyroscope %1",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "se connecter au cloud. Identifiant %1 Mot de passe %2",
|
||
writeToCloudStore: "écrire dans le cloud : identifiant %1 clé %2 valeur %3",
|
||
readFromCloudStore: "lire dans le cloud : identifiant %1 clé %2",
|
||
|
||
// IR Remote
|
||
readIRMessage: "attendre un message IR nom : %1 pendant : %2 ms",
|
||
sendIRMessage: "envoi du message préparé IR nommé %2 sur %1",
|
||
presetIRMessage: "préparer un message IR de nom %1 et contenu %2",
|
||
},
|
||
code: {
|
||
// Names of the functions in Python, or Blockly translated in JavaScript
|
||
turnLedOn: "turnLedOn",
|
||
turnLedOff: "turnLedOff",
|
||
setLedState: "setLedState",
|
||
|
||
isButtonPressed: "isButtonPressed",
|
||
isButtonPressedWithName : "isButtonPressed",
|
||
waitForButton: "waitForButton",
|
||
buttonWasPressed: "buttonWasPressed",
|
||
|
||
toggleLedState: "toggleLedState",
|
||
displayText: "displayText",
|
||
displayText2Lines: "displayText",
|
||
readTemperature: "readTemperature",
|
||
sleep: "sleep",
|
||
setServoAngle: "setServoAngle",
|
||
readRotaryAngle: "readRotaryAngle",
|
||
readDistance: "readDistance",
|
||
readLightIntensity: "readLightIntensity",
|
||
readHumidity: "readHumidity",
|
||
currentTime: "currentTime",
|
||
getTemperatureFromCloud: "getTemperatureFromCloud",
|
||
|
||
isLedOn: "isLedOn",
|
||
isLedOnWithName: "isLedOn",
|
||
|
||
setBuzzerNote: "setBuzzerNote",
|
||
getBuzzerNote: "getBuzzerNote",
|
||
setLedBrightness: "setLedBrightness",
|
||
getLedBrightness: "getLedBrightness",
|
||
getServoAngle: "getServoAngle",
|
||
|
||
setBuzzerState: "setBuzzerState",
|
||
setBuzzerNote: "setBuzzerNote",
|
||
|
||
turnBuzzerOn: "turnBuzzerOn",
|
||
turnBuzzerOff: "turnBuzzerOff",
|
||
isBuzzerOn: "isBuzzerOn",
|
||
isBuzzerOnWithName: "isBuzzerOn",
|
||
|
||
|
||
drawPoint: "drawPoint",
|
||
isPointSet: "isPointSet",
|
||
drawLine: "drawLine",
|
||
drawRectangle: "drawRectangle",
|
||
drawCircle: "drawCircle",
|
||
clearScreen: "clearScreen",
|
||
updateScreen: "updateScreen",
|
||
autoUpdate: "autoUpdate",
|
||
|
||
fill: "fill",
|
||
noFill: "noFill",
|
||
stroke: "stroke",
|
||
noStroke: "noStroke",
|
||
|
||
|
||
readAcceleration: "readAcceleration",
|
||
computeRotation: "computeRotation",
|
||
|
||
readSoundLevel: "readSoundLevel",
|
||
|
||
|
||
readMagneticForce: "readMagneticForce",
|
||
computeCompassHeading: "computeCompassHeading",
|
||
|
||
readInfraredState: "readInfraredState",
|
||
setInfraredState: "setInfraredState",
|
||
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity",
|
||
setGyroZeroAngle: "setGyroZeroAngle",
|
||
computeRotationGyro: "computeRotationGyro",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore",
|
||
writeToCloudStore: "writeToCloudStore",
|
||
readFromCloudStore: "readFromCloudStore",
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage",
|
||
sendIRMessage: "sendIRMessage",
|
||
presetIRMessage: "presetIRMessage",
|
||
},
|
||
description: {
|
||
// Descriptions of the functions in Python (optional)
|
||
turnLedOn: "turnLedOn() allume la LED",
|
||
turnLedOff: "turnLedOff() éteint la LED",
|
||
isButtonPressed: "isButtonPressed() retourne True si le bouton est enfoncé, False sinon",
|
||
isButtonPressedWithName: "isButtonPressed(button) retourne True si le bouton est enfoncé, False sinon",
|
||
waitForButton: "waitForButton(button) met en pause l'exécution jusqu'à ce que le bouton soit appuyé",
|
||
buttonWasPressed: "buttonWasPressed(button) indique si le bouton a été appuyé depuis le dernier appel à cette fonction",
|
||
setLedState: "setLedState(led, state) modifie l'état de la LED : True pour l'allumer, False pour l'éteindre",
|
||
toggleLedState: "toggleLedState(led) inverse l'état de la LED",
|
||
displayText: "displayText(line1, line2) affiche une ou deux lignes de texte. line2 est optionnel",
|
||
displayText2Lines: "displayText(line1, line2) affiche une ou deux lignes de texte. line2 est optionnel",
|
||
readTemperature: "readTemperature(thermometer) retourne la température ambiante",
|
||
sleep: "sleep(milliseconds) met en pause l'exécution pendant une durée en ms",
|
||
setServoAngle: "setServoAngle(servo, angle) change l'angle du servomoteur",
|
||
readRotaryAngle: "readRotaryAngle(potentiometer) retourne la position potentiomètre",
|
||
readDistance: "readDistance(distanceSensor) retourne la distance mesurée",
|
||
readLightIntensity: "readLightIntensity(lightSensor) retourne l'intensité lumineuse",
|
||
readHumidity: "readHumidity(hygrometer) retourne l'humidité ambiante",
|
||
currentTime: "currentTime() temps en millisecondes depuis le début du programme",
|
||
|
||
setLedBrightness: "setLedBrightness(led, brightness) règle l'intensité lumineuse de la LED",
|
||
getLedBrightness: "getLedBrightness(led) retourne l'intensité lumineuse de la LED",
|
||
getServoAngle: "getServoAngle(servo) retourne l'angle du servomoteur",
|
||
|
||
isLedOn: "isLedOn() retourne True si la LED est allumée, False si elle est éteinte",
|
||
isLedOnWithName: "isLedOn(led) retourne True si la LED est allumée, False sinon",
|
||
|
||
turnBuzzerOn: "turnBuzzerOn() allume le buzzer",
|
||
turnBuzzerOff: "turnBuzzerOff() éteint le buzzer",
|
||
|
||
isBuzzerOn: "isBuzzerOn() retourne True si le buzzer est allumé, False sinon",
|
||
isBuzzerOnWithName: "isBuzzerOn(buzzer) retourne True si le buzzer est allumé, False sinon",
|
||
|
||
setBuzzerState: "setBuzzerState(buzzer, state) modifie l'état du buzzer: True pour allumé, False sinon",
|
||
setBuzzerNote: "setBuzzerNote(buzzer, frequency) fait sonner le buzzer à la fréquence indiquée",
|
||
getBuzzerNote: "getBuzzerNote(buzzer) retourne la fréquence actuelle du buzzer",
|
||
|
||
getTemperatureFromCloud: "getTemperatureFromCloud(town) retourne la température dans la ville donnée",
|
||
|
||
drawPoint: "drawPoint(x, y) dessine un point de un pixel aux coordonnées données",
|
||
isPointSet: "isPointSet(x, y) retourne True si le point aux coordonées x, y est actif",
|
||
drawLine: "drawLine(x0, y0, x1, y1) dessine un segment commençant en x0, y0 jusqu'à x1, y1",
|
||
drawRectangle: "drawRectangle(x0, y0, width, height) dessine un rectangle, de coin haut gauche (x0,y0)",
|
||
drawCircle: "drawCircle(x0, y0, diameter) dessine un cercle de centre x0, y0 et de diamètre donné",
|
||
clearScreen: "clearScreen() efface le contenu de l'écran",
|
||
updateScreen: "updateScreen() mettre à jour l'écran",
|
||
autoUpdate: "autoUpdate(auto) change le mode d'actualisation de l'écran",
|
||
|
||
fill: "fill(color) Remplir les formes avec la couleur donnée",
|
||
noFill: "noFill() Ne pas remplir les formes",
|
||
stroke: "stroke(color) dessiner les bords des figures avec la couleur donnée",
|
||
noStroke: "noStroke() ne pas dessiner les bordures des figures",
|
||
|
||
|
||
readAcceleration: "readAcceleration(axis) lit l'accélération en m/s² sur l'axe (X, Y ou Z)",
|
||
computeRotation: "computeRotation(axis) calcule l'angle de rotation en degrés sur l'accéléromètre",
|
||
|
||
readSoundLevel: "readSoundLevel(port) retourne le volume ambiant",
|
||
|
||
|
||
readMagneticForce: "readMagneticForce(axis) retourne le champ magnétique (µT) sur l'axe (X, Y ou Z)",
|
||
computeCompassHeading: "computeCompassHeading() retourne la direction de la boussole en degrés",
|
||
|
||
readInfraredState: "readInfraredState(IRReceiver) retourne True si un signal infra-rouge est détecté, False sinon",
|
||
setInfraredState: "setInfraredState(IREmitter, state) modifie l'état de l'émetteur : True pour l'allumer, False pour l'éteindre",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity(axis) retourne la vitesse engulairee (°/s) du gyroscope",
|
||
setGyroZeroAngle: "setGyroZeroAngle() initialize le gyroscope à l'état 0",
|
||
computeRotationGyro: "computeRotationGyro(axis) calcule la rotation du gyroscope en degrés",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore(identifier, password) se connecter au cloud avec le nom d'utilisateur et le mot de passe donnés",
|
||
writeToCloudStore: "writeToCloudStore(identifier, key, value) écrire une valeur sur une clé dans le cloud",
|
||
readFromCloudStore: "readFromCloudStore(identifier, key) retourne la valeur lue dans le cloud de la clé donnée",
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage(irrec, timeout) attends un message infrarouge pendant le temps donné en millisecondes et le renvois",
|
||
sendIRMessage: "sendIRMessage(irtrans, name) envoi un message infrarouge précédement configurer avec le nom donné",
|
||
presetIRMessage: "presetIRMessage(name, data) configure un message infrarouge de nom name et de donné data",
|
||
},
|
||
constant: {
|
||
},
|
||
|
||
startingBlockName: "Programme", // Name for the starting block
|
||
messages: {
|
||
sensorNotFound: "Accès à un capteur ou actuateur inexistant : {0}.",
|
||
manualTestSuccess: "Test automatique validé.",
|
||
testSuccess: "Bravo ! La sortie est correcte",
|
||
wrongState: "Test échoué : <code>{0}</code> a été dans l'état {1} au lieu de {2} à t={3}ms.",
|
||
wrongStateDrawing: "Test échoué : <code>{0}</code> diffère de {1} pixels par rapport à l'affichage attendu à t={2}ms.",
|
||
wrongStateSensor: "Test échoué : votre programme n'a pas lu l'état de <code>{0}</code> après t={1}ms.",
|
||
programEnded: "programme terminé.",
|
||
piPlocked: "L'appareil est verrouillé. Déverrouillez ou redémarrez.",
|
||
cantConnect: "Impossible de se connecter à l'appareil.",
|
||
wrongVersion: "Votre Raspberry Pi a une version trop ancienne, mettez le à jour.",
|
||
sensorInOnlineMode: "Vous ne pouvez pas agir sur les capteurs en mode connecté.",
|
||
actuatorsWhenRunning: "Impossible de modifier les actionneurs lors de l'exécution d'un programme",
|
||
cantConnectoToUSB: 'Tentative de connexion par USB en cours, veuillez brancher votre Raspberry sur le port USB <i class="fas fa-circle-notch fa-spin"></i>',
|
||
cantConnectoToBT: 'Tentative de connection par Bluetooth, veuillez connecter votre appareil au Raspberry par Bluetooth <i class="fas fa-circle-notch fa-spin"></i>',
|
||
canConnectoToUSB: "Connecté en USB.",
|
||
canConnectoToBT: "Connecté en Bluetooth.",
|
||
noPortsAvailable: "Aucun port compatible avec ce {0} n'est disponible (type {1})",
|
||
sensor: "capteur",
|
||
actuator: "actionneur",
|
||
removeConfirmation: "Êtes-vous certain de vouloir retirer ce capteur ou actuateur?",
|
||
remove: "Retirer",
|
||
keep: "Garder",
|
||
minutesago: "Last seen {0} minutes ago",
|
||
hoursago: "Last seen more than one hour ago",
|
||
drawing: "dessin",
|
||
timeLabel: "Temps",
|
||
seconds: "secondes",
|
||
|
||
changeBoard: "Changer de carte",
|
||
connect: "Connecter",
|
||
install: "Installer",
|
||
config: "Config",
|
||
|
||
|
||
raspiConfig: "Configuration du Raspberry Pi",
|
||
local: "Local",
|
||
schoolKey: "Indiquez un identifiant d'école",
|
||
connectList: "Sélectionnez un appareil à connecter dans la liste suivante",
|
||
enterIpAddress: "ou entrez son adesse IP",
|
||
getPiList: "Obtenir la liste",
|
||
connectTroughtTunnel: "Connecter à travers le France-ioi tunnel",
|
||
|
||
connectToLocalhost: "Connecter l'interface à la machine sur laquelle tourne ce navigateur",
|
||
connectToWindowLocation: "Connecter au Raspberry Pi depuis lequel cette page est chargée",
|
||
|
||
connectToDevice: "Connecter l'appareil",
|
||
disconnectFromDevice: "Déconnecter",
|
||
|
||
|
||
irReceiverTitle: "Recevoir des codes infrarouges",
|
||
directIrControl: "Dirigez votre télécommande vers votre carte QuickPi et appuyez sur un des boutons",
|
||
getIrCode: "Recevoir un code",
|
||
closeDialog: "Fermer",
|
||
|
||
irRemoteControl: "Télécommande IR",
|
||
|
||
noIrPresets: "Veuillez utiliser la fonction de préparation de messages IR pour ajouter des commandes de télécommande",
|
||
irEnableContinous: "Activer l'émission IR en continu",
|
||
irDisableContinous: "Désactiver l'émission IR en continu",
|
||
|
||
connectToLocalHost: "Connecter l'interface à la machine sur laquelle tourne ce navigateur",
|
||
|
||
up: "up",
|
||
down: "down",
|
||
left: "left",
|
||
right: "right",
|
||
center: "center",
|
||
|
||
on: "On",
|
||
off: "Off",
|
||
|
||
grovehat: "Grove Base Hat for Raspberry Pi",
|
||
quickpihat: "France IOI QuickPi Hat",
|
||
pinohat: "Raspberry Pi without hat",
|
||
led: "LED",
|
||
blueled: "LED bleue",
|
||
greenled: "LED verte",
|
||
orangeled: "LED orange",
|
||
redled: "LED rouge",
|
||
buzzer: "Buzzer",
|
||
grovebuzzer: "Grove Buzzer",
|
||
quickpibuzzer: "Quick Pi Passive Buzzer",
|
||
servo: "Servo Motor",
|
||
screen: "Screen",
|
||
grove16x2lcd: "Grove 16x2 LCD",
|
||
oled128x32: "128x32 Oled Screen",
|
||
irtrans: "IR Transmiter",
|
||
button: "Button",
|
||
fivewaybutton: "5 way button",
|
||
tempsensor: "Temperature sensor",
|
||
groveanalogtempsensor: "Grove Analog tempeature sensor",
|
||
quickpigyrotempsensor: "Quick Pi Accelerometer+Gyroscope temperature sensor",
|
||
dht11tempsensor: "DHT11 Tempeature Sensor",
|
||
potentiometer: "Potentiometer",
|
||
lightsensor: "Light sensor",
|
||
distancesensor: "Capteur de distance",
|
||
timeofflightranger: "Time of flight distance sensor",
|
||
ultrasonicranger: "Capteur de distance à ultrason",
|
||
humiditysensor: "Humidity sensor",
|
||
soundsensor: "Sound sensor",
|
||
accelerometerbmi160: "Accelerometer sensor (BMI160)",
|
||
gyrobmi160: "Gyropscope sensor (BMI160)",
|
||
maglsm303c: "Magnetometer sensor (LSM303C)",
|
||
irreceiver: "IR Receiver",
|
||
cloudstore: "Cloud Store",
|
||
addcomponent: "Ajouter un composant",
|
||
selectcomponent: "Sélectionnez un composant à ajouter à votre Raspberry Pi et attachez-le à un port.",
|
||
add: "Ajouter",
|
||
builtin: "(builtin)",
|
||
chooseBoard: "Choisissez votre carte",
|
||
nameandports: "Noms et ports des capteurs et actionneurs QuickPi",
|
||
name: "Name",
|
||
port: "Port",
|
||
state: "State",
|
||
|
||
cloudTypes: {
|
||
object: "Dictionnaire",
|
||
array: "Tableau",
|
||
boolean: "Booléen",
|
||
number: "Nombre",
|
||
string: "Chaîne de caractère"
|
||
},
|
||
cloudMissingKey: "Test échoué : Il vous manque la clé {0} dans le cloud.",
|
||
cloudMoreKey: "Test échoué : La clé {0} est en trop dans le cloud",
|
||
cloudUnexpectedKeyCorrection: "Test échoué : La clé {0} n'étais pas attendu dans le cloud",
|
||
cloudPrimitiveWrongKey: "Test échoué : À la clé {0} du cloud, la valeur {1} était attendue au lieu de {2}",
|
||
cloudArrayWrongKey: "Test échoué : Le tableau à la clé {0} du cloud diffère de celui attendu.",
|
||
cloudDictionaryWrongKey: "Test échoué : Le dictionnaire à la clé {0} diffère de celui attendu",
|
||
cloudWrongType: "Test échoué : Vous avez stocké une valeur de type \"{0}\" dans la clé {1} du cloud, mais le type \"{2}\" était attendu.",
|
||
|
||
cloudKeyNotExists: "La clé n'existe pas : {0} ",
|
||
cloudWrongValue: "Clé {0} : la valeur {2} n'est pas celle attendue, {1}.",
|
||
cloudUnexpectedKey: "La clé {0} n'est pas une clé attendue",
|
||
hello: "Bonjour",
|
||
|
||
getTemperatureFromCloudWrongValue: "getTemperatureFromCloud: {0} n'est pas une ville supportée par getTemperatureFromCloud",
|
||
|
||
experiment: "Expérimenter",
|
||
validate: "Valider",
|
||
validate1: "Valider 1",
|
||
validate2: "Valider 2",
|
||
validate3: "Valider 3",
|
||
|
||
sensorNameBuzzer: "buzzer",
|
||
sensorNameLed: "led",
|
||
sensorNameRedLed: "redled",
|
||
sensorNameGreenLed: "greenled",
|
||
sensorNameBlueLed: "blueled",
|
||
sensorNameOrangeLed: "orangeled",
|
||
sensorNameScreen: "screen",
|
||
sensorNameIrTrans: "irtran",
|
||
sensorNameIrRecv: "irrec",
|
||
sensorNameMicrophone: "micro",
|
||
sensorNameTemperature: "temp",
|
||
sensorNameGyroscope: "gyroscope",
|
||
sensorNameMagnetometer: "magneto",
|
||
sensorNameDistance: "distance",
|
||
sensorNameAccelerometer: "accel",
|
||
sensorNameButton: "button",
|
||
sensorNameLight: "light",
|
||
sensorNameStick: "stick",
|
||
sensorNameServo: "servo",
|
||
sensorNameHumidity: "humidity",
|
||
sensorNamePotentiometer: "pot",
|
||
sensorNameCloudStore: "cloud"
|
||
},
|
||
concepts: {
|
||
quickpi_start: 'Créer un programme',
|
||
quickpi_validation: 'Valider son programme',
|
||
quickpi_buzzer: 'Buzzer',
|
||
quickpi_led: 'LEDs',
|
||
quickpi_button: 'Boutons et manette',
|
||
quickpi_screen: 'Écran',
|
||
quickpi_draw: 'Dessiner',
|
||
quickpi_range: 'Capteur de distance',
|
||
quickpi_servo: 'Servomoteur',
|
||
quickpi_thermometer: 'Thermomètre',
|
||
quickpi_microphone: 'Microphone',
|
||
quickpi_light_sensor: 'Capteur de luminosité',
|
||
quickpi_accelerometer: 'Accéléromètre',
|
||
quickpi_wait: 'Gestion du temps',
|
||
quickpi_magneto: 'Magnétomètre',
|
||
quickpi_ir_receiver: 'Récepteur infrarouge',
|
||
quickpi_ir_emitter: 'Émetteur infrarouge',
|
||
quickpi_potentiometer: "Potentiomètre",
|
||
quickpi_gyroscope: "Gyroscope",
|
||
quickpi_cloud: 'Stockage dans le cloud'
|
||
}
|
||
},
|
||
es: {
|
||
label: {
|
||
// Labels for the blocks
|
||
sleep: "esperar %1 milisegundos",
|
||
currentTime: "tiempo transcurrido en milisegundos",
|
||
|
||
turnLedOn: "encender el LED",
|
||
turnLedOff: "apagar el LED",
|
||
|
||
setLedState: "cambiar el LED %1 a %2 ",
|
||
toggleLedState: "invertir el estado del LED %1",
|
||
|
||
isLedOn: "LED encendido",
|
||
isLedOnWithName: "LED %1 encendido",
|
||
|
||
setLedBrightness: "Cambiar el brillo de %1 a %2",
|
||
getLedBrightness: "Obtener el brillo de %1",
|
||
|
||
turnBuzzerOn: "encender el zumbador",
|
||
turnBuzzerOff: "apagar el zumbador",
|
||
setBuzzerState: "cambiar el zumbador %1 a %2",
|
||
isBuzzerOn: "zumbador encendido",
|
||
isBuzzerOnWithName: "zumbador %1 encendido",
|
||
|
||
setBuzzerNote: "frequencia de reproducción %2Hz en %1",
|
||
getBuzzerNote: "frequncia del zumbador %1",
|
||
|
||
isButtonPressed: "botón presionado",
|
||
isButtonPressedWithName: "botón %1 presionado",
|
||
waitForButton: "esperar a que se presione un botón",
|
||
buttonWasPressed: "el botón ha sido presionado",
|
||
|
||
displayText: "desplegar texto %1",
|
||
displayText2Lines: "desplegar texto Linea 1 : %1 Linea 2 : %2",
|
||
|
||
readTemperature: "temperatura ambiente",
|
||
getTemperatureFromCloud: "temperatura de la ciudad %1", // TODO: verify
|
||
|
||
readRotaryAngle: "estado del potenciómetro %1",
|
||
readDistance: "distancia medida por %1",
|
||
readLightIntensity: "intensidad de luz",
|
||
readHumidity: "humedad ambiental",
|
||
|
||
setServoAngle: "cambiar el ángulo de el servo %1 a %2°",
|
||
getServoAngle: "ángulo del servo %1",
|
||
|
||
|
||
drawPoint: "dibuja un pixel",
|
||
isPointSet: "este pixel esta dibujado",
|
||
drawLine: "linea desde x₀: %1 y₀: %2 hasta x₁: %3 y₁: %4",
|
||
drawRectangle: "rectángulo x: %1 y: %2 largo: %3 alto: %4",
|
||
drawCircle: "circulo x₀: %1 y₀: %2 diametro: %3",
|
||
clearScreen: "limpiar toda la pantalla",
|
||
updateScreen: "actualizar pantalla",
|
||
autoUpdate: "modo de actualización de pantalla automática",
|
||
|
||
fill: "establecer el color de fondo en %1",
|
||
noFill: "no rellenar figuras",
|
||
stroke: "color de los bordes %1",
|
||
noStroke: "no dibujar los contornos",
|
||
|
||
readAcceleration: "aceleración en m/s² en el eje %1",
|
||
computeRotation: "cálculo del ángulo de rotación (°) en el acelerómetro %1",
|
||
readSoundLevel: "volumen de sonido",
|
||
|
||
readMagneticForce: "campo magnético (µT) en %1",
|
||
computeCompassHeading: "dirección de la brújula en (°)",
|
||
|
||
readInfraredState: "infrarrojos detectados en %1",
|
||
setInfraredState: "cambiar emisor de infrarrojos %1 a %2",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "velocidad angular (°/s) del guroscopio %1",
|
||
setGyroZeroAngle: "inicializar el giroscopio a estado cero",
|
||
computeRotationGyro: "calcular la rotación del giroscopio %1",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "conectar a la nube. Usuario %1 Contraseña %2",
|
||
writeToCloudStore: "escribir en la nube : Usuario %1 llave %2 valor %3",
|
||
readFromCloudStore: "leer de la nube : Usuario %1 lave %2",
|
||
|
||
// IR Remote
|
||
readIRMessage: "esperar un mensaje de infrarrojos : %1 durante : %2 ms",
|
||
sendIRMessage: "enviar el mensaje por infrarrojos %2 por %1",
|
||
presetIRMessage: "preparar un mensaje de infrarrojos con el nombre %1 y el contenido %2",
|
||
},
|
||
code: {
|
||
// Names of the functions in Python, or Blockly translated in JavaScript
|
||
turnLedOn: "turnLedOn",
|
||
turnLedOff: "turnLedOff",
|
||
setLedState: "setLedState",
|
||
|
||
isButtonPressed: "isButtonPressed",
|
||
isButtonPressedWithName : "isButtonPressed",
|
||
waitForButton: "waitForButton",
|
||
buttonWasPressed: "buttonWasPressed",
|
||
|
||
toggleLedState: "toggleLedState",
|
||
displayText: "displayText",
|
||
displayText2Lines: "displayText",
|
||
readTemperature: "readTemperature",
|
||
sleep: "sleep",
|
||
setServoAngle: "setServoAngle",
|
||
readRotaryAngle: "readRotaryAngle",
|
||
readDistance: "readDistance",
|
||
readLightIntensity: "readLightIntensity",
|
||
readHumidity: "readHumidity",
|
||
currentTime: "currentTime",
|
||
getTemperatureFromCloud: "getTemperatureFromCloud",
|
||
|
||
isLedOn: "isLedOn",
|
||
isLedOnWithName: "isLedOn",
|
||
|
||
setBuzzerNote: "setBuzzerNote",
|
||
getBuzzerNote: "getBuzzerNote",
|
||
setLedBrightness: "setLedBrightness",
|
||
getLedBrightness: "getLedBrightness",
|
||
getServoAngle: "getServoAngle",
|
||
|
||
setBuzzerState: "setBuzzerState",
|
||
setBuzzerNote: "setBuzzerNote",
|
||
|
||
turnBuzzerOn: "turnBuzzerOn",
|
||
turnBuzzerOff: "turnBuzzerOff",
|
||
isBuzzerOn: "isBuzzerOn",
|
||
isBuzzerOnWithName: "isBuzzerOn",
|
||
|
||
|
||
drawPoint: "drawPoint",
|
||
isPointSet: "isPointSet",
|
||
drawLine: "drawLine",
|
||
drawRectangle: "drawRectangle",
|
||
drawCircle: "drawCircle",
|
||
clearScreen: "clearScreen",
|
||
updateScreen: "updateScreen",
|
||
autoUpdate: "autoUpdate",
|
||
|
||
fill: "fill",
|
||
noFill: "noFill",
|
||
stroke: "stroke",
|
||
noStroke: "noStroke",
|
||
|
||
|
||
readAcceleration: "readAcceleration",
|
||
computeRotation: "computeRotation",
|
||
|
||
readSoundLevel: "readSoundLevel",
|
||
|
||
|
||
readMagneticForce: "readMagneticForce",
|
||
computeCompassHeading: "computeCompassHeading",
|
||
|
||
readInfraredState: "readInfraredState",
|
||
setInfraredState: "setInfraredState",
|
||
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity",
|
||
setGyroZeroAngle: "setGyroZeroAngle",
|
||
computeRotationGyro: "computeRotationGyro",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore",
|
||
writeToCloudStore: "writeToCloudStore",
|
||
readFromCloudStore: "readFromCloudStore",
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage",
|
||
sendIRMessage: "sendIRMessage",
|
||
presetIRMessage: "presetIRMessage",
|
||
},
|
||
description: {
|
||
// Descriptions of the functions in Python (optional)
|
||
turnLedOn: "turnLedOn() enciende el LED",
|
||
turnLedOff: "turnLedOff() apaga el led LED",
|
||
isButtonPressed: "isButtonPressed() devuelve True si el boton esta presionado, False de otra manera",
|
||
isButtonPressedWithName: "isButtonPressed(button) devuelve True si el boton esta presionado, False de otra manera",
|
||
waitForButton: "waitForButton(button) pausa la ejecución hasta que se presiona el botón",
|
||
buttonWasPressed: "buttonWasPressed(button) indica si se ha pulsado el botón desde la última llamada a esta función",
|
||
setLedState: "setLedState(led, state) modifica el estado del LED: True para encenderlo, False para apagarlo",
|
||
toggleLedState: "toggleLedState(led) invierte el estado del LED",
|
||
displayText: "displayText(line1, line2) muestra una o dos líneas de texto. line2 es opcional",
|
||
displayText2Lines: "displayText(line1, line2) muestra una o dos líneas de texto. line2 es opcional",
|
||
readTemperature: "readTemperature(thermometer) devuelve la temperatura ambiente",
|
||
sleep: "sleep(milliseconds) pausa la ejecución por un tiempo en milisegundos",
|
||
setServoAngle: "setServoAngle(servo, angle) cambiar el ángulo del servomotor",
|
||
readRotaryAngle: "readRotaryAngle(potentiometer) devuelve la posición del potenciómetro",
|
||
readDistance: "readDistance(distanceSensor) devuelve la distancia medida",
|
||
readLightIntensity: "readLightIntensity(lightSensor) devuelve la intensidad de la luz",
|
||
readHumidity: "readHumidity(hygrometer) devuelve la humedad ambiental",
|
||
currentTime: "currentTime() tiempo en milisegundos desde el inicio del programa",
|
||
|
||
setLedBrightness: "setLedBrightness(led, brightness) ajusta la intensidad de la luz del LED",
|
||
getLedBrightness: "getLedBrightness(led) devuelve la intensidad de luz del LED",
|
||
getServoAngle: "getServoAngle(servo) devuelve el ángulo del servomotor",
|
||
|
||
isLedOn: "isLedOn() devuelve True si el LED está encendido, False si está apagado",
|
||
isLedOnWithName: "isLedOn(led) devuelve True si el LED está encendido, False si está apagado",
|
||
|
||
turnBuzzerOn: "turnBuzzerOn() enciende el zumbador",
|
||
turnBuzzerOff: "turnBuzzerOff() apaga el zumbador",
|
||
|
||
isBuzzerOn: "isBuzzerOn() devuelve True si el zumbador está encendido, False si está apagado",
|
||
isBuzzerOnWithName: "isBuzzerOn(buzzer) devuelve True si el zumbador está encendido, False si está apagado",
|
||
|
||
setBuzzerState: "setBuzzerState(buzzer, state) modifica el estado del zumbador: Verdadero para encendido, Falso para apagado",
|
||
setBuzzerNote: "setBuzzerNote(buzzer, frequency) suena el zumbador en la frecuencia indicada",
|
||
getBuzzerNote: "getBuzzerNote(buzzer) devuelve la frecuencia actual del zumbador",
|
||
|
||
getTemperatureFromCloud: "getTemperatureFromCloud(town) obtiene la temperatura de la ciudad", // TODO: Verify
|
||
|
||
drawPoint: "drawPoint(x, y) dibuja un punto en las coordenadas x, y",
|
||
isPointSet: "isPointSet(x, y) devuelve True se dibujó sobre el punto x, y, False de lo contrario",
|
||
drawLine: "drawLine(x0, y0, x1, y1) dibuja una linea empezando desde el punto x0, x1, hasta el punto x1, y1",
|
||
drawRectangle: "drawRectangle(x0, y0, width, height) dibuja un rectángulo empezando en el punto x0, y0 con el ancho y altura dados",
|
||
drawCircle: "drawCircle(x0, y0, diameter) dibuja un circulo con centro en x0, y0 y el diametro dado",
|
||
clearScreen: "clearScreen() limpia toda la pantalla",
|
||
updateScreen: "updateScreen() actualiza los contenidos de la pantalla",
|
||
autoUpdate: "autoUpdate(auto) cambia el modo de actualización de pantalla automatica",
|
||
|
||
fill: "fill(color) rellenar las figuras con el color dado",
|
||
noFill: "noFill() no rellenar las figuras",
|
||
stroke: "stroke(color) dibujar los bordes de las figuras con el color dado",
|
||
noStroke: "noStroke() no dibujar los bordes de las figuras",
|
||
|
||
|
||
readAcceleration: "readAcceleration(axis) leer la acceleración (m/s²) en el eje (X, Y o Z)",
|
||
computeRotation: "computeRotation(axis) calcular el ángulo de rotación (°) en el acelerómetro",
|
||
|
||
readSoundLevel: "readSoundLevel(port) devuelve el volumen del sonido ambiente",
|
||
|
||
|
||
readMagneticForce: "readMagneticForce(axis) devuelve el campo magnético (µT) en el eje (X, Y o Z)",
|
||
computeCompassHeading: "computeCompassHeading() devuelve la dirección de la brujula en grados",
|
||
|
||
readInfraredState: "readInfraredState() devuelve True si se detecta una señal infrarroja, Falso de otra manera",
|
||
setInfraredState: "setInfraredState(state) si se le pasa True enciende el transmisor infrarrojo, Falso lo apaga",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity(axis) devuelve la velocidad angular (°/s) del gyroscopio",
|
||
setGyroZeroAngle: "setGyroZeroAngle() inicializa el giroscopio a estado cero",
|
||
computeRotationGyro: "computeRotationGyro(axis) calcula la rotación del giroscopio (°)",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore(identifier, password) se conecta a la nube con el usuario y password dados",
|
||
writeToCloudStore: "writeToCloudStore(identifier, key, value) escribe un valor a un llave en la nube",
|
||
readFromCloudStore: "readFromCloudStore(identifier, key) devuelve un valor leido de la nube de la llave dada",
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage(irrec, timeout) espera por un mensaje infrarrojo y lo devuelve durante el tiempo dado en milisegundos",
|
||
sendIRMessage: "sendIRMessage(irtrans, name) envia un mensaje infrarrojo previamente configurado con el nombre dado",
|
||
presetIRMessage: "presetIRMessage(name, data) configura un mensaje infrarrojo con el nombre y datos dados",
|
||
},
|
||
constant: {
|
||
},
|
||
|
||
startingBlockName: "Programa", // Name for the starting block
|
||
messages: {
|
||
sensorNotFound: "Acceso a un componente inexistente: {0}.",
|
||
manualTestSuccess: "Prueba automática validada.",
|
||
testSuccess: "Bien hecho! El resultado es correcto",
|
||
wrongState: "Prueba fallida: <code>{0}</code> estaba en etado {1} en lugar de {2} en t={3}ms.",
|
||
wrongStateDrawing: "Prueba fallida: <code>{0}</code> difiere en {1} píxeles de la visualización esperada en t = {2} ms.",
|
||
wrongStateSensor: "Prueba fallida: su programa no leyó el estado de <code>{0}</code> después de t = {1} ms.",
|
||
programEnded: "Programa completado.",
|
||
piPlocked: "El dispositivo está bloqueado. Desbloquear o reiniciar.",
|
||
cantConnect: "No puede conectarse al dispositivo.",
|
||
wrongVersion: "El software en tu Raspberry Pi es demasiado antiguo, actualízalo.",
|
||
sensorInOnlineMode: "No se pueden modificar sensores en modo conectado.",
|
||
actuatorsWhenRunning: "No se pueden cambiar los actuadores mientras se ejecuta un programa",
|
||
cantConnectoToUSB: 'Intentado conectarse por USB, conecta tu Raspberry Pi al puerto USB <i class="fas fa-circle-notch fa-spin"></i>',
|
||
cantConnectoToBT: 'Intentando conectarse por Bluetooth, conecta tu Raspberry Pi por Bluetooth <i class="fas fa-circle-notch fa-spin"></i>',
|
||
canConnectoToUSB: "USB Conectado.",
|
||
canConnectoToBT: "Bluetooth Conectado.",
|
||
noPortsAvailable: "No hay ningún puerto compatible con {0} disponible (type {1})",
|
||
sensor: "Sensor",
|
||
actuator: "Actuador",
|
||
removeConfirmation: "¿Estás seguro de que deseas quitar este componente?",
|
||
remove: "Eliminar",
|
||
keep: "Mantener",
|
||
minutesago: "Visto por última vez hace {0} minutos",
|
||
hoursago: "Visto por ultima vez hace mas de una hora",
|
||
drawing: "dibujando",
|
||
timeLabel: "Tiempo",
|
||
seconds: "segundos",
|
||
|
||
changeBoard: "Cambiar tablero",
|
||
connect: "Conectar",
|
||
install: "Instalar",
|
||
config: "Configuración",
|
||
|
||
|
||
raspiConfig: "Configuración de Raspberry Pi",
|
||
local: "Local",
|
||
schoolKey: "Ingresa una identificación de la escuela",
|
||
connectList: "Selecciona un dispositivo para conectarte de la siguiente lista",
|
||
enterIpAddress: "o ingresa una dirección IP",
|
||
getPiList: "Obtener la lista",
|
||
connectTroughtTunnel: "Conéctate a través del túnel de France-ioi",
|
||
|
||
connectToLocalhost: "Conectarse al dispositivo que ejecuta este navegador",
|
||
connectToWindowLocation: "Conéctate a la Raspberry Pi desde la que se carga esta página",
|
||
|
||
connectToDevice: "Conectar al dispositivo",
|
||
disconnectFromDevice: "Desconectar",
|
||
|
||
|
||
irReceiverTitle: "Recibir códigos infrarrojos",
|
||
directIrControl: "Apunta tu control remoto a tu tablero QuickPi y presiona uno de los botones",
|
||
getIrCode: "Recibir un código",
|
||
closeDialog: "Cerrar",
|
||
|
||
irRemoteControl: "Control remoto Infrarrojo",
|
||
|
||
noIrPresets: "Utiliza la función de preparación de mensajes IR para agregar comandos de control remoto",
|
||
irEnableContinous: "Activar la emisión IR continua",
|
||
irDisableContinous: "Desactivar la emisión IR continua",
|
||
|
||
getTemperatureFromCloudWrongValue: "getTemperatureFromCloud: {0} is not a town supported by getTemperatureFromCloud", // TODO: translate
|
||
|
||
up: "arriba",
|
||
down: "abajo",
|
||
left: "izquierda",
|
||
right: "derecha",
|
||
center: "centro",
|
||
|
||
on: "Encendido",
|
||
off: "Apagado",
|
||
|
||
grovehat: "Sombrero Grove para Raspberry Pi",
|
||
quickpihat: "Sobrero QuickPi de France IOI",
|
||
pinohat: "Raspberry Pi sin sombrero",
|
||
led: "LED",
|
||
blueled: "LED azul",
|
||
greenled: "LED verde",
|
||
orangeled: "LED naranja",
|
||
redled: "LED rojo",
|
||
buzzer: "Zumbador",
|
||
grovebuzzer: "Zumbador Grove",
|
||
quickpibuzzer: "Zumbador passive de QuickPi",
|
||
servo: "Motor Servo",
|
||
screen: "Pantalla",
|
||
grove16x2lcd: "Pantalla Grove 16x2",
|
||
oled128x32: "Pantalla 128x32 Oled",
|
||
irtrans: "Transmisor de infrarrojos",
|
||
button: "Botón",
|
||
fivewaybutton: "Botón de 5 direcciones",
|
||
tempsensor: "Sensor de temperatura",
|
||
groveanalogtempsensor: "Sensor de temperatura analógico Grove",
|
||
quickpigyrotempsensor: "Sensor de temperaturea en el Acelerometro y Gyroscopio de QuickPi",
|
||
dht11tempsensor: "Sensor de Temperatura DHT11",
|
||
potentiometer: "Potenciómetro",
|
||
lightsensor: "Sensor de luz",
|
||
distancesensor: "Sensor de distancia",
|
||
timeofflightranger: "Sensor de distancia por rebote de luz",
|
||
ultrasonicranger: "Sensor de distancia por últrasonido",
|
||
humiditysensor: "Sensor de humedad",
|
||
soundsensor: "Sensor de sonido",
|
||
accelerometerbmi160: "Acelerómetro (BMI160)",
|
||
gyrobmi160: "Giroscopio (BMI160)",
|
||
maglsm303c: "Magnetómetro (LSM303C)",
|
||
irreceiver: "Receptor de infrarrojos",
|
||
cloudstore: "Almacenamiento en la nube",
|
||
addcomponent: "Agregar componente",
|
||
selectcomponent: "Selecciona un componente para agregar a tu Raspberry Pi y conéctalo a un puerto.",
|
||
add: "Agregar",
|
||
builtin: "(incorporado)",
|
||
chooseBoard: "Elije tu tablero",
|
||
nameandports: "Nombres y puertos de sensores y actuadores QuickPi",
|
||
name: "Nombre",
|
||
port: "Puerto",
|
||
state: "Estado",
|
||
|
||
cloudTypes: {
|
||
object: "Dictionnaire", // TODO: translate (dictionary)
|
||
array: "Tableau", // TODO: translate
|
||
boolean: "Booléen", // TODO: translate
|
||
number: "Nombre", // TODO: translate
|
||
string: "Chaîne de caractère" // TODO: translate
|
||
},
|
||
cloudMissingKey: "Test échoué : Il vous manque la clé {0} dans le cloud.", // TODO: translate
|
||
cloudMoreKey: "Test échoué : La clé {0} est en trop dans le cloud", // TODO: translate
|
||
cloudUnexpectedKeyCorrection: "Test échoué : La clé {0} n'étais pas attendu dans le cloud", // TODO: translate
|
||
cloudPrimitiveWrongKey: "Test échoué : À la clé {0} du cloud, la valeur {1} était attendue au lieu de {2}", // TODO: translate
|
||
cloudArrayWrongKey: "Test échoué : Le tableau à la clé {0} du cloud diffère de celui attendu.", // TODO: translate
|
||
cloudDictionaryWrongKey: "Test échoué : Le dictionnaire à la clé {0} diffère de celui attendu", // TODO: translate
|
||
cloudWrongType: "Test échoué : Vous avez stocké une valeur de type \"{0}\" dans la clé {1} du cloud, mais le type \"{2}\" était attendu.", // TODO: translate
|
||
|
||
cloudKeyNotExists: "La llave no existe : {0} ",
|
||
cloudWrongValue: "Llave {0}: el valor {2} no es el esperado, {1}.",
|
||
cloudUnexpectedKey: "La llave {0} no es una llave esperada",
|
||
hello: "Hola",
|
||
experiment: "Experimentar",
|
||
validate: "Validar",
|
||
validate1: "Validar 1",
|
||
validate2: "Validar 2",
|
||
validate3: "Validar 3",
|
||
|
||
sensorNameBuzzer: "timbre",
|
||
sensorNameLed: "led",
|
||
sensorNameRedLed: "ledrojo",
|
||
sensorNameGreenLed: "ledverde",
|
||
sensorNameBlueLed: "ledazul",
|
||
sensorNameScreen: "pantalla",
|
||
sensorNameIrTrans: "tranir",
|
||
sensorNameIrRecv: "recir",
|
||
sensorNameMicrophone: "micro",
|
||
sensorNameTemperature: "temp",
|
||
sensorNameGyroscope: "gyro",
|
||
sensorNameMagnetometer: "magneto",
|
||
sensorNameDistance: "distancia",
|
||
sensorNameAccelerometer: "acel",
|
||
sensorNameButton: "boton",
|
||
sensorNameLight: "luz",
|
||
sensorNameStick: "stick",
|
||
sensorNameServo: "servo",
|
||
sensorNameHumidity: "humedad",
|
||
sensorNamePotentiometer: "pot",
|
||
sensorNameCloudStore: "nube",
|
||
},
|
||
concepts: {
|
||
quickpi_start: 'Crea tu primer programa y ejecútalo',
|
||
quickpi_validation: 'Prueba y valida tus programas',
|
||
quickpi_buzzer: 'Zumbador',
|
||
quickpi_led: 'LEDs o diodos electroluminiscentes',
|
||
quickpi_button: 'Botón',
|
||
quickpi_screen: 'Pantalla',
|
||
quickpi_draw: 'Dibujar sobre la pantalla',
|
||
quickpi_range: 'Sensor de distancia',
|
||
quickpi_servo: 'Servo motor',
|
||
quickpi_thermometer: 'Termómetro',
|
||
quickpi_microphone: 'Micrófono',
|
||
quickpi_light_sensor: 'Sensor de luz',
|
||
quickpi_accelerometer: 'Acelerómetro',
|
||
quickpi_wait: 'Gestión del tiempo',
|
||
quickpi_magneto: 'Magnetómetro', // TODO: verify
|
||
quickpi_ir_receiver: 'Receptor de infrarrojos', // TODO: verify
|
||
quickpi_ir_emitter: 'Emisor de infrarrojos', // TODO: verify
|
||
quickpi_potentiometer: "Potenciómetro", // TODO: verify
|
||
quickpi_gyroscope: "giroscopio", // TODO: verify
|
||
quickpi_cloud: 'Almacenamiento en la nube'
|
||
}
|
||
},
|
||
it: { // Italian strings // TODO
|
||
label: {
|
||
// Labels for the blocks
|
||
sleep: "attendi %1 millisecondei",
|
||
currentTime: "tempo calcolato in millisecondi",
|
||
|
||
turnLedOn: "accendi il LED",
|
||
turnLedOff: "spegni il LED",
|
||
|
||
setLedState: "passa il LED da %1 a %2 ",
|
||
toggleLedState: "inverti il LED %1",
|
||
|
||
isLedOn: "LED acceso",
|
||
isLedOnWithName: "LED %1 acceso",
|
||
|
||
setLedBrightness: "imposta la luminosità da %1 a %2",
|
||
getLedBrightness: "leggi la luminosità di %1",
|
||
|
||
turnBuzzerOn: "accendi il cicalino",
|
||
turnBuzzerOff: "spegni il cicalino",
|
||
setBuzzerState: "imposta il cicalino %1 a %2",
|
||
isBuzzerOn: "cicalino acceso",
|
||
isBuzzerOnWithName: "cicalino %1 acceso",
|
||
|
||
setBuzzerNote: "suona la frequenza %2Hz su %1",
|
||
getBuzzerNote: "frequenza del cicalino %1",
|
||
|
||
isButtonPressed: "pulsante premuto",
|
||
isButtonPressedWithName: "pulsante %1 premuto",
|
||
waitForButton: "attendi una pressione sul pulsante",
|
||
buttonWasPressed: "il pulsante è stato premuto",
|
||
|
||
displayText: "mostra %1",
|
||
displayText2Lines: "mostra Riga 1 : %1 Riga 2 : %2",
|
||
|
||
readTemperature: "temperatura ambiente",
|
||
getTemperatureFromCloud: "temperatura della cità %1", // TODO: verify
|
||
|
||
readRotaryAngle: "stato del potenziometro %1",
|
||
readDistance: "distanza misurata all'%1",
|
||
readLightIntensity: "intensità luminosa",
|
||
readHumidity: "umidità ambiente",
|
||
|
||
setServoAngle: "metti il servomotore %1 all'angolo %2",
|
||
getServoAngle: "angolo del servomotore %1",
|
||
|
||
|
||
drawPoint: "draw pixel",
|
||
isPointSet: "is pixel set in screen",
|
||
drawLine: "riga x₀: %1 y₀: %2 x₁: %3 y₁: %4",
|
||
drawRectangle: "rettangolo x₀: %1 y₀: %2 larghezza₀: %3 altezza₀: %4",
|
||
drawCircle: "cerchio x₀: %1 y₀: %2 diametro₀: %3",
|
||
clearScreen: "cancella tutta la schermata",
|
||
updateScreen: "aggiorna schermata",
|
||
autoUpdate: "aggiornamento automatico della schermata",
|
||
|
||
fill: "metti il colore di fondo a %1",
|
||
noFill: "non riempire le forme",
|
||
stroke: "impostare il colore del percorso a %1",
|
||
noStroke: "non disegnare i contorni",
|
||
|
||
readAcceleration: "accelerazione in (m/s²) nell'asse %1",
|
||
computeRotation: "calcolo dell'angolo di rotazione (°) sull'accelerometro %1",
|
||
readSoundLevel: "volume sonoro",
|
||
|
||
readMagneticForce: "campo magnetico (µT) su %1",
|
||
computeCompassHeading: "direzione della bussola in (°)",
|
||
|
||
readInfraredState: "infrarosso rilevato su %1",
|
||
setInfraredState: "imposta il trasmettitore a infrarossi %1 a %2",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "velocità angolare (°/s) del giroscopio %1",
|
||
setGyroZeroAngle: "inizializza il giroscopio allo stato zero",
|
||
computeRotationGyro: "calcola la rotazione del giroscopio %1",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connettersi al cloud. Nome utente %1 Password %2",
|
||
writeToCloudStore: "scrivi nel cloud : id %1 chiave %2 valore %3",
|
||
readFromCloudStore: "leggi nel cloud : id %1 chiave %2",
|
||
|
||
// IR Remote
|
||
readIRMessage: "attendi un messaggio IR nome : %1 per : %2 ms",
|
||
sendIRMessage: "invio del messaggio prepato IR nominato %2 su %1",
|
||
presetIRMessage: "prepara un messaggio IR con il nome %1 e contenuto %2",
|
||
},
|
||
code: {
|
||
// Names of the functions in Python, or Blockly translated in JavaScript
|
||
turnLedOn: "turnLedOn",
|
||
turnLedOff: "turnLedOff",
|
||
setLedState: "setLedState",
|
||
|
||
isButtonPressed: "isButtonPressed",
|
||
isButtonPressedWithName : "isButtonPressed",
|
||
waitForButton: "waitForButton",
|
||
buttonWasPressed: "buttonWasPressed",
|
||
|
||
toggleLedState: "toggleLedState",
|
||
displayText: "displayText",
|
||
displayText2Lines: "displayText",
|
||
readTemperature: "readTemperature",
|
||
sleep: "sleep",
|
||
setServoAngle: "setServoAngle",
|
||
readRotaryAngle: "readRotaryAngle",
|
||
readDistance: "readDistance",
|
||
readLightIntensity: "readLightIntensity",
|
||
readHumidity: "readHumidity",
|
||
currentTime: "currentTime",
|
||
getTemperatureFromCloud: "getTemperatureFromCloud",
|
||
|
||
isLedOn: "isLedOn",
|
||
isLedOnWithName: "isLedOn",
|
||
|
||
setBuzzerNote: "setBuzzerNote",
|
||
getBuzzerNote: "getBuzzerNote",
|
||
setLedBrightness: "setLedBrightness",
|
||
getLedBrightness: "getLedBrightness",
|
||
getServoAngle: "getServoAngle",
|
||
|
||
setBuzzerState: "setBuzzerState",
|
||
setBuzzerNote: "setBuzzerNote",
|
||
|
||
turnBuzzerOn: "turnBuzzerOn",
|
||
turnBuzzerOff: "turnBuzzerOff",
|
||
isBuzzerOn: "isBuzzerOn",
|
||
isBuzzerOnWithName: "isBuzzerOn",
|
||
|
||
|
||
drawPoint: "drawPoint",
|
||
isPointSet: "isPointSet",
|
||
drawLine: "drawLine",
|
||
drawRectangle: "drawRectangle",
|
||
drawCircle: "drawCircle",
|
||
clearScreen: "clearScreen",
|
||
updateScreen: "updateScreen",
|
||
autoUpdate: "autoUpdate",
|
||
|
||
fill: "fill",
|
||
noFill: "noFill",
|
||
stroke: "stroke",
|
||
noStroke: "noStroke",
|
||
|
||
|
||
readAcceleration: "readAcceleration",
|
||
computeRotation: "computeRotation",
|
||
|
||
readSoundLevel: "readSoundLevel",
|
||
|
||
|
||
readMagneticForce: "readMagneticForce",
|
||
computeCompassHeading: "computeCompassHeading",
|
||
|
||
readInfraredState: "readInfraredState",
|
||
setInfraredState: "setInfraredState",
|
||
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity",
|
||
setGyroZeroAngle: "setGyroZeroAngle",
|
||
computeRotationGyro: "computeRotationGyro",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore",
|
||
writeToCloudStore: "writeToCloudStore",
|
||
readFromCloudStore: "readFromCloudStore",
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage",
|
||
sendIRMessage: "sendIRMessage",
|
||
presetIRMessage: "presetIRMessage",
|
||
},
|
||
description: {
|
||
// Descriptions of the functions in Python (optional)
|
||
turnLedOn: "turnLedOn() accendi il LED",
|
||
turnLedOff: "turnLedOff() spegni il LED",
|
||
isButtonPressed: "isButtonPressed() riporta True se il pulsante è premuto, False nel caso contrario",
|
||
isButtonPressedWithName: "isButtonPressed(button) riporta True se il pulsante è premuto, False se non lo è",
|
||
waitForButton: "waitForButton(button) sospende l'esecuzione fino a quando non viene premuto il pulsante",
|
||
buttonWasPressed: "buttonWasPressed(button) indica se il tasto è stato premuto dall'ultima volta che questa funzione è stata utilizzata.",
|
||
setLedState: "setLedState(led, state) modifica lo stato del LED : True per accenderlo, False per spegnerlo",
|
||
toggleLedState: "toggleLedState(led) inverte lo stato del LED",
|
||
displayText: "displayText(line1, line2) mostra una o due righe di testo. La line2 è opzionale",
|
||
displayText2Lines: "displayText(line1, line2) mostra una o due righe di testo. La line2 è opzionale",
|
||
readTemperature: "readTemperature(thermometer) riporta la temperatura ambiente",
|
||
sleep: "sleep(milliseconds) mette in pausa l'esecuzione per una durata in ms",
|
||
setServoAngle: "setServoAngle(servo, angle) cambia l'angolo del servomotore",
|
||
readRotaryAngle: "readRotaryAngle(potentiometer) riporta la posizione del potenziometro",
|
||
readDistance: "readDistance(distanceSensor) riporta la distanza misurata",
|
||
readLightIntensity: "readLightIntensity(lightSensor) riporta l'intensità luminosa",
|
||
readHumidity: "readHumidity(hygrometer) riporta l'umidità dell'ambiente",
|
||
currentTime: "currentTime() tempo in millisecondi dall'avvio del programma",
|
||
|
||
setLedBrightness: "setLedBrightness(led, brightness) regola l'intensità luminosa del LED",
|
||
getLedBrightness: "getLedBrightness(led) riporta l'intensità luminosa del LED",
|
||
getServoAngle: "getServoAngle(servo) riporta l'angolo del servomotore",
|
||
|
||
isLedOn: "isLedOn() riporta True se il LED è acceso, False se è spento",
|
||
isLedOnWithName: "isLedOn(led) riporta True se il LED è acceso, False se è spento",
|
||
|
||
turnBuzzerOn: "turnBuzzerOn() accende il cicalino",
|
||
turnBuzzerOff: "turnBuzzerOff() spegne il cicalino",
|
||
|
||
isBuzzerOn: "isBuzzerOn() riporta True se il cicalino è acceso, False se è spento",
|
||
isBuzzerOnWithName: "isBuzzerOn(buzzer) riporta True se il cicalino è acceso, False se è spento",
|
||
|
||
setBuzzerState: "setBuzzerState(buzzer, state) modifica lo stato del cicalino: True per acceso, False nel caso contrario",
|
||
setBuzzerNote: "setBuzzerNote(buzzer, frequency) fa suonare il cicalino alla frequenza indicata",
|
||
getBuzzerNote: "getBuzzerNote(buzzer) riporta la frequenza attuale del cicalino",
|
||
|
||
getTemperatureFromCloud: "getTemperatureFromCloud(town) get the temperature from the town given", // TODO: Translate
|
||
|
||
drawPoint: "drawPoint(x, y) draw a point of 1 pixel at given coordinates", // TODO: Translate
|
||
isPointSet: "isPointSet(x, y) return True if the point at coordinates x, y is on", // TODO: Translate
|
||
drawLine: "drawLine(x0, y0, x1, y1) draw a line starting at x0, y0 to x1, y1", // TODO: Translate
|
||
drawRectangle: "drawRectangle(x0, y0, width, height) disegna un rettangolo, con angolo in alto a sinistra (x0,y0)",
|
||
drawCircle: "drawCircle(x0, y0, diameter) draw a circle of center x0, y0 and of given diameter", // TODO: Translate
|
||
clearScreen: "clearScreen() cancella il contenuto della schermata",
|
||
updateScreen: "updateScreen() update screen content", // TODO: Translate
|
||
autoUpdate: "autoUpdate(auto) change the screen actualisation mode", // TODO: Translate
|
||
|
||
fill: "fill(color) fill the shapes with the color given", // TODO: Translate
|
||
noFill: "noFill() do not fill the shapes", // TODO: Translate
|
||
stroke: "stroke(color) draw the borders of shapes with the color given", // TODO: Translate
|
||
noStroke: "noStroke() do not draw the borders of shapes", // TODO: Translate
|
||
|
||
|
||
readAcceleration: "readAcceleration(axis) read the acceleration (m/s²) in the axis (X, Y or Z)", // TODO: Translate
|
||
computeRotation: "computeRotation(axis) compute the rotation angle (°) in the accelerometro", // TODO: Translate
|
||
|
||
readSoundLevel: "readSoundLevel(port) return the ambien sound", // TODO: Translate
|
||
|
||
|
||
readMagneticForce: "readMagneticForce(axis) return the magnetic force (µT) in the axis (X, Y ou Z)", // TODO : Translate
|
||
computeCompassHeading: "computeCompassHeading() return the compass direction in degres", // TODO: Translate
|
||
|
||
readInfraredState: "readInfraredState(IRReceiver) riporta True se viene rilevato un segnale infrarosso, False nel caso in contrario",
|
||
setInfraredState: "setInfraredState(IREmitter, state) modifica lo stato del trasmettitore : True per accenderlo, False per spegnerlo",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity(axis) return the angular speed (°/s) of the gyroscope", // TODO: Translate
|
||
setGyroZeroAngle: "setGyroZeroAngle() initialize the gyroscope at the 0 state", // TODO: Translate
|
||
computeRotationGyro: "computeRotationGyro(axis) compute the rotations of the gyroscope in degres", // TODO: Translate
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore(identifier, password) connect to cloud store with the given username and password", // TODO: Translate
|
||
writeToCloudStore: "writeToCloudStore(identifier, key, value) write a value at a key to the cloud", // TODO: Translate
|
||
readFromCloudStore: "readFromCloudStore(identifier, key) read the value at the given key from the cloud", // TODO: Translate
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage(irrec, timeout) wait for an IR message during the given time and then return it", // TODO: Translate
|
||
sendIRMessage: "sendIRMessage(irtrans, name) send an IR message previously configured with the given name", // TODO: Translate
|
||
presetIRMessage: "presetIRMessage(name, data) configure an IR message with the given name and data" // TODO: Translate
|
||
},
|
||
constant: {
|
||
},
|
||
|
||
startingBlockName: "Programma", // Name for the starting block
|
||
messages: {
|
||
sensorNotFound: "Accesso a un sensore o attuatore inesistente : {0}.",
|
||
manualTestSuccess: "Test automatico convalidato.",
|
||
testSuccess: "Bravo ! Il risultato è corretto",
|
||
wrongState: "Test fallito : <code>{0}</code> è rimasto nello stato {1} invece di {2} a t={3}ms.",
|
||
wrongStateDrawing: "Test fallito : <code>{0}</code> differisce di {1} pixel rispetto alla visualizzazione prevista a t={2}ms.",
|
||
wrongStateSensor: "Test fallito : il tuo programma non ha letto lo stato di <code>{0}</code> dopo t={1}ms.",
|
||
programEnded: "programma terminato.",
|
||
piPlocked: "L'unità è bloccata. Sbloccare o riavviare.",
|
||
cantConnect: "Impossibile connettersi all'apparecchio.",
|
||
wrongVersion: "Il tuo Raspberry Pi è una versione troppo vecchia, aggiornala.",
|
||
sensorInOnlineMode: "Non è possibile agire sui sensori in modalità connessa.",
|
||
actuatorsWhenRunning: "Impossibile modificare gli azionatori durante l'esecuzione di un programma",
|
||
cantConnectoToUSB: 'Tentativo di connessione via USB in corso, si prega di collegare il Raspberry alla porta USB. <i class="fas fa-circle-notch fa-spin"></i>',
|
||
cantConnectoToBT: 'Tentativo di connessione via Bluetooth, si prega di collegare il dispositivo al Raspberry via Bluetooth <i class="fas fa-circle-notch fa-spin"></i>',
|
||
canConnectoToUSB: "Connesso via USB.",
|
||
canConnectoToBT: "Connesso via Bluetooth.",
|
||
noPortsAvailable: "Non è disponibile alcuna porta compatibile con questo {0} (type {1})",
|
||
sensor: "sensore",
|
||
actuator: "azionatore",
|
||
removeConfirmation: "Sei sicuro di voler rimuovere questo sensore o attuatore?",
|
||
remove: "Rimuovi",
|
||
keep: "Tieni",
|
||
minutesago: "Last seen {0} minutes ago",
|
||
hoursago: "Last seen more than one hour ago",
|
||
drawing: "disegno",
|
||
timeLabel: "Tempo",
|
||
seconds: "secondi",
|
||
|
||
changeBoard: "Cambia scheda",
|
||
connect: "Connetti",
|
||
install: "Installa",
|
||
config: "Config",
|
||
|
||
|
||
raspiConfig: "Configurazione del Raspberry Pi",
|
||
local: "Local",
|
||
schoolKey: "Indica un ID scolastico",
|
||
connectList: "Seleziona un apparecchio da connettere nel seguente elenco",
|
||
enterIpAddress: "o inserisci il tuo indirizzo IP",
|
||
getPiList: "Ottieni l'elenco",
|
||
connectTroughtTunnel: "Collegamento attraverso il canale France-ioi",
|
||
|
||
connectToLocalhost: "Collegamento dell'interfaccia al computer su cui funziona questo browser",
|
||
connectToWindowLocation: "Connettiti al Rasberry Pi da cui è stata caricata questa pagina",
|
||
|
||
connectToDevice: "Connetti l'apparecchio",
|
||
disconnectFromDevice: "Disconnetti",
|
||
|
||
|
||
irReceiverTitle: "Ricevi codici infrarossi",
|
||
directIrControl: "Punta il telecomando verso la scheda QuickPi e premi uno dei tasti.s",
|
||
getIrCode: "Ricevi un codice",
|
||
closeDialog: "Chiudi",
|
||
|
||
irRemoteControl: "Telecomando IR",
|
||
|
||
noIrPresets: "Si prega di utilizzare la funzione di preparazione dei messaggi IR per aggiungere comandi di controllo remoto.",
|
||
irEnableContinous: "Attiva la trasmissione IR continua",
|
||
irDisableContinous: "Disattiva la trasmissione IR continua",
|
||
|
||
connectToLocalHost: "Collegamento dell'interfaccia alla periferica su cui funziona questo browser",
|
||
|
||
up: "up",
|
||
down: "down",
|
||
left: "left",
|
||
right: "right",
|
||
center: "center",
|
||
|
||
on: "On",
|
||
off: "Off",
|
||
|
||
getTemperatureFromCloudWrongValue: "getTemperatureFromCloud: {0} is not a town supported by getTemperatureFromCloud", // TODO: translate
|
||
|
||
grovehat: "Grove Base Hat for Raspberry Pi",
|
||
quickpihat: "France IOI QuickPi Hat",
|
||
pinohat: "Raspberry Pi without hat",
|
||
led: "LED",
|
||
blueled: "LED blu",
|
||
greenled: "LED verde",
|
||
orangeled: "LED arancione",
|
||
redled: "LED rosso",
|
||
buzzer: "Buzzer",
|
||
grovebuzzer: "Grove Buzzer",
|
||
quickpibuzzer: "Quick Pi Passive Buzzer",
|
||
servo: "Servomotore",
|
||
screen: "Screen",
|
||
grove16x2lcd: "Grove 16x2 LCD",
|
||
oled128x32: "128x32 Oled Screen",
|
||
irtrans: "IR Transmiter",
|
||
button: "Button",
|
||
fivewaybutton: "5 way button",
|
||
tempsensor: "Temperature sensor",
|
||
groveanalogtempsensor: "Grove Analog tempeature sensor",
|
||
quickpigyrotempsensor: "Quick Pi Accelerometer+Gyroscope temperature sensor",
|
||
dht11tempsensor: "DHT11 Tempeature Sensor",
|
||
potentiometer: "Potentiometer",
|
||
lightsensor: "Light sensor",
|
||
distancesensor: "Sensore di distanza",
|
||
timeofflightranger: "Time of flight distance sensor",
|
||
ultrasonicranger: "Sensore di distanza a ultrasuoni",
|
||
humiditysensor: "Humidity sensor",
|
||
soundsensor: "Sound sensor",
|
||
accelerometerbmi160: "Accelerometer sensor (BMI160)",
|
||
gyrobmi160: "Gyropscope sensor (BMI160)",
|
||
maglsm303c: "Magnetometer sensor (LSM303C)",
|
||
irreceiver: "IR Receiver",
|
||
cloudstore: "Cloud Store",
|
||
addcomponent: "Aggiungi un componente",
|
||
selectcomponent: "Seleziona un componente da aggiungere al tuo Raspberry Pi e collegalo a una porta.",
|
||
add: "Aggiungi",
|
||
builtin: "(builtin)",
|
||
chooseBoard: "Scegli la tua scheda",
|
||
nameandports: "Nomi e porte dei sensori e azionatori QuickPi",
|
||
name: "Name",
|
||
port: "Port",
|
||
state: "State",
|
||
|
||
cloudTypes: {
|
||
object: "Dictionnaire", // TODO: translate (dictionary)
|
||
array: "Tableau", // TODO: translate
|
||
boolean: "Booléen", // TODO: translate
|
||
number: "Nombre", // TODO: translate
|
||
string: "Chaîne de caractère" // TODO: translate
|
||
},
|
||
cloudMissingKey: "Test échoué : Il vous manque la clé {0} dans le cloud.", // TODO: translate
|
||
cloudMoreKey: "Test échoué : La clé {0} est en trop dans le cloud", // TODO: translate
|
||
cloudUnexpectedKeyCorrection: "Test échoué : La clé {0} n'étais pas attendu dans le cloud", // TODO: translate
|
||
cloudPrimitiveWrongKey: "Test échoué : À la clé {0} du cloud, la valeur {1} était attendue au lieu de {2}", // TODO: translate
|
||
cloudArrayWrongKey: "Test échoué : Le tableau à la clé {0} du cloud diffère de celui attendu.", // TODO: translate
|
||
cloudDictionaryWrongKey: "Test échoué : Le dictionnaire à la clé {0} diffère de celui attendu", // TODO: translate
|
||
cloudWrongType: "Test échoué : Vous avez stocké une valeur de type \"{0}\" dans la clé {1} du cloud, mais le type \"{2}\" était attendu.", // TODO: translate
|
||
|
||
cloudKeyNotExists: "La chiave non esiste : {0} ",
|
||
cloudWrongValue: "Chiave {0} : il valore {2} non è quello previsto, {1}.",
|
||
cloudUnexpectedKey: "La chiave {0} non è una chiave prevista",
|
||
hello: "Buongiorno",
|
||
|
||
experiment: "Testa",
|
||
validate: "Convalida",
|
||
validate1: "Convalida 1",
|
||
validate2: "Convalida 2",
|
||
validate3: "Convalida 3",
|
||
|
||
sensorNameBuzzer: "buzzer",
|
||
sensorNameLed: "led",
|
||
sensorNameRedLed: "redled",
|
||
sensorNameGreenLed: "greenled",
|
||
sensorNameBlueLed: "blueled",
|
||
sensorNameOrangeLed: "orangeled",
|
||
sensorNameScreen: "screen",
|
||
sensorNameIrTrans: "irtran",
|
||
sensorNameIrRecv: "irrec",
|
||
sensorNameMicrophone: "micro",
|
||
sensorNameTemperature: "temp",
|
||
sensorNameGyroscope: "gyroscope",
|
||
sensorNameMagnetometer: "magneto",
|
||
sensorNameDistance: "distance",
|
||
sensorNameAccelerometer: "accel",
|
||
sensorNameButton: "button",
|
||
sensorNameLight: "light",
|
||
sensorNameStick: "stick",
|
||
sensorNameServo: "servo",
|
||
sensorNameHumidity: "humidity",
|
||
sensorNamePotentiometer: "pot",
|
||
sensorNameCloudStore: "cloud",
|
||
},
|
||
concepts: {
|
||
quickpi_start: 'Crea un programma',
|
||
quickpi_validation: 'Convalida il tuo programma',
|
||
quickpi_buzzer: 'Cicalino',
|
||
quickpi_led: 'LED',
|
||
quickpi_button: 'Pulsanti e joystick',
|
||
quickpi_screen: 'Schermo',
|
||
quickpi_draw: 'Disegna',
|
||
quickpi_range: 'Sensore di distanza',
|
||
quickpi_servo: 'Servomotore',
|
||
quickpi_thermometer: 'Termometro',
|
||
quickpi_microphone: 'Microfono',
|
||
quickpi_light_sensor: 'Sensore di luminosità',
|
||
quickpi_accelerometer: 'Accelerometro',
|
||
quickpi_wait: 'Gestione del tempo',
|
||
quickpi_magneto: 'Magnetometro', // TODO: verify
|
||
quickpi_ir_receiver: 'Ricevitore a infrarossi', // TODO: verify
|
||
quickpi_ir_emitter: 'Emettitore a infrarossi', // TODO: verify
|
||
quickpi_potentiometer: "Potenziometro", // TODO: verify
|
||
quickpi_gyroscope: "giroscopio", // TODO: verify
|
||
quickpi_cloud: 'Memorizzazione nel cloud'
|
||
}
|
||
},
|
||
|
||
none: {
|
||
comment: {
|
||
// Comments for each block, used in the auto-generated documentation for task writers
|
||
turnLedOn: "Turns on a light connected to Raspberry",
|
||
turnLedOff: "Turns off a light connected to Raspberry",
|
||
isButtonPressed: "Returns the state of a button, Pressed means True and not pressed means False",
|
||
waitForButton: "Stops program execution until a button is pressed",
|
||
buttonWasPressed: "Returns true if the button has been pressed and will clear the value",
|
||
setLedState: "Change led state in the given port",
|
||
toggleLedState: "If led is on, turns it off, if it's off turns it on",
|
||
isButtonPressedWithName: "Returns the state of a button, Pressed means True and not pressed means False",
|
||
displayText: "Display text in LCD screen",
|
||
displayText2Lines: "Display text in LCD screen (two lines)",
|
||
readTemperature: "Read Ambient temperature",
|
||
sleep: "pause program execute for a number of seconds",
|
||
setServoAngle: "Set servo motor to an specified angle",
|
||
readRotaryAngle: "Read state of potentiometer",
|
||
readDistance: "Read distance using ultrasonic sensor",
|
||
readLightIntensity: "Read light intensity",
|
||
readHumidity: "lire l'humidité ambiante",
|
||
currentTime: "returns current time",
|
||
setBuzzerState: "sonnerie",
|
||
setBuzzerNote: "sonnerie note",
|
||
getTemperatureFromCloud: "Get temperature from town",
|
||
setBuzzerNote: "Set buzzer note",
|
||
getBuzzerNote: "Get buzzer note",
|
||
setLedBrightness: "Set Led Brightness",
|
||
getLedBrightness: "Get Led Brightness",
|
||
getServoAngle: "Get Servo Angle",
|
||
isLedOn: "Get led state",
|
||
isLedOnWithName: "Get led state",
|
||
turnBuzzerOn: "Turn Buzzer on",
|
||
turnBuzzerOff: "Turn Buzzer off",
|
||
isBuzzerOn: "Is Buzzer On",
|
||
isBuzzerOnWithName: "get buzzer state",
|
||
drawPoint: "drawPoint",
|
||
isPointSet: "isPointSet",
|
||
drawLine: "drawLine",
|
||
drawRectangle: "drawRectangle",
|
||
drawCircle: "drawCircle",
|
||
clearScreen: "clearScreen",
|
||
updateScreen: "updateScreen",
|
||
autoUpdate: "autoUpdate",
|
||
fill: "fill",
|
||
noFill: "noFill",
|
||
stroke: "stroke",
|
||
noStroke: "noStroke",
|
||
readAcceleration: "readAcceleration",
|
||
computeRotation: "computeRotation",
|
||
readSoundLevel: "readSoundLevel",
|
||
readMagneticForce: "readMagneticForce",
|
||
computeCompassHeading: "computeCompassHeading",
|
||
readInfraredState: "readInfraredState",
|
||
setInfraredState: "setInfraredState",
|
||
|
||
// Gyroscope
|
||
readAngularVelocity: "readAngularVelocity",
|
||
setGyroZeroAngle: "setGyroZeroAngle",
|
||
computeRotationGyro: "computeRotationGyro",
|
||
|
||
//Internet store
|
||
connectToCloudStore: "connectToCloudStore",
|
||
writeToCloudStore: "writeToCloudStore",
|
||
readFromCloudStore: "readFromCloudStore",
|
||
|
||
// IR Remote
|
||
readIRMessage: "readIRMessage",
|
||
sendIRMessage: "sendIRMessage",
|
||
presetIRMessage: "presetIRMessage",
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
var buzzerSound = {
|
||
context: null,
|
||
default_freq: 200,
|
||
channels: {},
|
||
muted: {},
|
||
|
||
getContext: function() {
|
||
if(!this.context) {
|
||
this.context = ('AudioContext' in window) || ('webkitAudioContext' in window) ? new(window.AudioContext || window.webkitAudioContext)() : null;
|
||
}
|
||
return this.context;
|
||
},
|
||
|
||
startOscillator: function(freq) {
|
||
var o = this.context.createOscillator();
|
||
o.type = 'sine';
|
||
o.frequency.value = freq;
|
||
o.connect(this.context.destination);
|
||
o.start();
|
||
return o;
|
||
},
|
||
|
||
|
||
start: function(channel, freq=this.default_freq) {
|
||
if(!this.channels[channel]) {
|
||
this.channels[channel] = {
|
||
muted: false
|
||
}
|
||
}
|
||
if(this.channels[channel].freq === freq) {
|
||
return;
|
||
}
|
||
var context = this.getContext();
|
||
if(!context) {
|
||
return;
|
||
}
|
||
this.stop(channel);
|
||
|
||
if (freq == 0 || this.channels[channel].muted) {
|
||
return;
|
||
}
|
||
|
||
this.channels[channel].oscillator = this.startOscillator(freq);
|
||
this.channels[channel].freq = freq;
|
||
},
|
||
|
||
stop: function(channel) {
|
||
if(this.channels[channel]) {
|
||
this.channels[channel].oscillator && this.channels[channel].oscillator.stop();
|
||
delete this.channels[channel].oscillator;
|
||
delete this.channels[channel].freq;
|
||
}
|
||
},
|
||
|
||
mute: function(channel) {
|
||
if(!this.channels[channel]) {
|
||
this.channels[channel] = {
|
||
muted: true
|
||
}
|
||
return;
|
||
}
|
||
this.channels[channel].muted = true;
|
||
this.channels[channel].oscillator && this.channels[channel].oscillator.stop();
|
||
delete this.channels[channel].oscillator;
|
||
},
|
||
|
||
unmute: function(channel) {
|
||
if(!this.channels[channel]) {
|
||
this.channels[channel] = {
|
||
muted: false
|
||
}
|
||
return;
|
||
}
|
||
this.channels[channel].muted = false;
|
||
if(this.channels[channel].freq) {
|
||
this.channels[channel].oscillator = this.startOscillator(this.channels[channel].freq);
|
||
}
|
||
},
|
||
|
||
isMuted: function(channel) {
|
||
if(this.channels[channel]) {
|
||
return this.channels[channel].muted;
|
||
}
|
||
return false;
|
||
},
|
||
|
||
stopAll: function() {
|
||
for(var channel in this.channels) {
|
||
if(this.channels.hasOwnProperty(channel)) {
|
||
this.stop(channel);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
var gyroscope3D = (function() {
|
||
|
||
var instance;
|
||
|
||
function createInstance(width, height) {
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
|
||
// debug code start
|
||
/*
|
||
canvas.style.zIndex = 99999;
|
||
canvas.style.position = 'fixed';
|
||
canvas.style.top = '0';
|
||
canvas.style.left = '0';
|
||
document.body.appendChild(canvas);
|
||
*/
|
||
// debug code end
|
||
|
||
try {
|
||
var renderer = new zen3d.Renderer(canvas, { antialias: true, alpha: true });
|
||
} catch(e) {
|
||
return false;
|
||
}
|
||
|
||
renderer.glCore.state.colorBuffer.setClear(0, 0, 0, 0);
|
||
|
||
var scene = new zen3d.Scene();
|
||
|
||
var lambert = new zen3d.LambertMaterial();
|
||
lambert.diffuse.setHex(0x468DDF);
|
||
|
||
var cube_geometry = new zen3d.CubeGeometry(10, 2, 10);
|
||
var cube = new zen3d.Mesh(cube_geometry, lambert);
|
||
cube.position.x = 0;
|
||
cube.position.y = 0;
|
||
cube.position.z = 0;
|
||
scene.add(cube);
|
||
|
||
var ambientLight = new zen3d.AmbientLight(0xffffff, 2);
|
||
scene.add(ambientLight);
|
||
|
||
var pointLight = new zen3d.PointLight(0xffffff, 1, 100);
|
||
pointLight.position.set(-20, 40, 10);
|
||
scene.add(pointLight);
|
||
|
||
var camera = new zen3d.Camera();
|
||
camera.position.set(0, 13, 13);
|
||
camera.lookAt(new zen3d.Vector3(0, 0, 0), new zen3d.Vector3(0, 1, 0));
|
||
camera.setPerspective(45 / 180 * Math.PI, width / height, 1, 1000);
|
||
scene.add(camera);
|
||
|
||
|
||
return {
|
||
resize: function(width, height) {
|
||
camera.setPerspective(
|
||
45 / 180 * Math.PI,
|
||
width / height,
|
||
1,
|
||
1000
|
||
);
|
||
},
|
||
|
||
render: function(ax, ay, az) {
|
||
cube.euler.x = Math.PI * ax / 360;
|
||
cube.euler.y = Math.PI * ay / 360;
|
||
cube.euler.z = Math.PI * az / 360;
|
||
renderer.render(scene, camera);
|
||
return canvas;
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
getInstance: function(width, height) {
|
||
if(!instance) {
|
||
instance = createInstance(width, height);
|
||
} else {
|
||
instance.resize(width, height)
|
||
}
|
||
return instance;
|
||
}
|
||
}
|
||
|
||
})();
|
||
|
||
|
||
|
||
function QuickStore(rwidentifier, rwpassword) {
|
||
var url = 'https://cloud.quick-pi.org';
|
||
var connected = (rwidentifier === undefined);
|
||
|
||
function post(path, data, callback) {
|
||
$.ajax({
|
||
type: 'POST',
|
||
url: url + path,
|
||
crossDomain: true,
|
||
data: data,
|
||
dataType: 'json',
|
||
success: callback
|
||
});
|
||
}
|
||
|
||
return {
|
||
connected: rwpassword,
|
||
read: function(identifier, key, callback) {
|
||
var data = {
|
||
prefix: identifier,
|
||
key: key
|
||
};
|
||
post('/api/data/read', data, callback);
|
||
},
|
||
|
||
write: function(identifier, key, value, callback) {
|
||
if (identifier != rwidentifier)
|
||
{
|
||
callback({
|
||
sucess: false,
|
||
message: "Écriture sur un identifiant en lecture seule : " + identifier,
|
||
});
|
||
}
|
||
else {
|
||
var data = {
|
||
prefix: identifier,
|
||
password: rwpassword,
|
||
key: key,
|
||
value: JSON.stringify(value)
|
||
};
|
||
post('/api/data/write', data, callback);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// This is a template of library for use with quickAlgo.
|
||
var getContext = function (display, infos, curLevel) {
|
||
|
||
// Local language strings for each language
|
||
var introControls = null;
|
||
|
||
// Create a base context
|
||
var context = quickAlgoContext(display, infos);
|
||
|
||
// we set the lib involved to Quick-Pi
|
||
context.title = "Quick-Pi";
|
||
|
||
// Import our localLanguageStrings into the global scope
|
||
var strings = context.setLocalLanguageStrings(quickPiLocalLanguageStrings);
|
||
|
||
context.disableAutoCompletion = false;
|
||
|
||
// Some data can be made accessible by the library through the context object
|
||
context.quickpi = {};
|
||
|
||
|
||
// List of concepts to be included by conceptViewer
|
||
context.getConceptList = function() {
|
||
var conceptList = [{id: 'language', ignore: true}];
|
||
var quickPiConceptList = [
|
||
{
|
||
id: 'quickpi_start',
|
||
isBase: true,
|
||
order: 1,
|
||
python: []
|
||
},
|
||
{
|
||
id: 'quickpi_validation',
|
||
isBase: true,
|
||
order: 2,
|
||
python: []
|
||
},
|
||
{
|
||
id: 'quickpi_buzzer',
|
||
order: 200,
|
||
python: ['setBuzzerState', 'setBuzzerNote','turnBuzzerOn','turnBuzzerOff', 'setBuzzerState',
|
||
'getBuzzerNote', 'isBuzzerOn']
|
||
},
|
||
{
|
||
id: 'quickpi_led',
|
||
order: 201,
|
||
python: ['setLedState','toggleLedState','turnLedOn','turnLedOff', 'setLedBrightness', 'getLedBrightness', 'isLedOn']
|
||
},
|
||
{
|
||
id: 'quickpi_button',
|
||
order: 202,
|
||
python: ['isButtonPressed', 'isButtonPressedWithName', 'waitForButton', 'buttonWasPressed']
|
||
},
|
||
{
|
||
id: 'quickpi_screen',
|
||
order: 203,
|
||
python: ['displayText']
|
||
},
|
||
{
|
||
id: 'quickpi_draw',
|
||
order: 203,
|
||
python: ['drawRectangle','drawLine','drawCircle', 'drawPoint', 'clearScreen', 'fill', 'noFill',
|
||
'stroke', 'noStroke','updateScreen', 'autoUpdate', 'isPointSet']
|
||
},
|
||
{
|
||
id: 'quickpi_range',
|
||
order: 204,
|
||
python: ['readDistance']
|
||
},
|
||
{
|
||
id: 'quickpi_servo',
|
||
order: 205,
|
||
python: ['setServoAngle', 'getServoAngle']
|
||
},
|
||
{
|
||
id: 'quickpi_thermometer',
|
||
order: 206,
|
||
python: ['readTemperature']
|
||
},
|
||
{
|
||
id: 'quickpi_microphone',
|
||
order: 207,
|
||
python: ['readSoundLevel']
|
||
},
|
||
{
|
||
id: 'quickpi_light_sensor',
|
||
order: 208,
|
||
python: ['readLightIntensity']
|
||
},
|
||
{
|
||
id: 'quickpi_accelerometer',
|
||
order: 209,
|
||
python: ['readAcceleration', 'computeRotation']
|
||
},
|
||
{
|
||
id: 'quickpi_wait',
|
||
order: 250,
|
||
python: ['sleep', 'currentTime']
|
||
},
|
||
{
|
||
id: 'quickpi_magneto',
|
||
order: 210,
|
||
python: ['readMagneticForce', 'computeCompassHeading']
|
||
},
|
||
{
|
||
id: 'quickpi_ir_receiver',
|
||
order: 211,
|
||
python: ['readInfraredState', 'readIRMessage']
|
||
},
|
||
{
|
||
id: "quickpi_ir_emitter",
|
||
order: 212,
|
||
python: ["setInfraredState", "sendIRMessage", "presetIRMessage"]
|
||
},
|
||
{
|
||
id: "quickpi_potentiometer",
|
||
order: 213,
|
||
python: ["readRotaryAngle"]
|
||
},
|
||
{
|
||
id: "quickpi_gyroscope",
|
||
order: 214,
|
||
python: ["readAngularVelocity", "setGyroZeroAngle", "computeRotationGyro"]
|
||
},
|
||
{
|
||
id: 'quickpi_cloud',
|
||
order: 220,
|
||
python: ['writeToCloudStore','connectToCloudStore','readFromCloudStore', 'getTemperatureFromCloud']
|
||
}
|
||
];
|
||
|
||
if(window.stringsLanguage == 'fr' || !strings.concepts) {
|
||
var conceptStrings = quickPiLocalLanguageStrings.fr.concepts;
|
||
var conceptIndex = 'quickpi.html';
|
||
} else {
|
||
var conceptStrings = strings.concepts;
|
||
var conceptIndex = 'quickpi_' + window.stringsLanguage + '.html';
|
||
}
|
||
var conceptBaseUrl = 'https://static4.castor-informatique.fr/help/'+conceptIndex;
|
||
|
||
for(var i = 0; i < quickPiConceptList.length; i++) {
|
||
var concept = quickPiConceptList[i];
|
||
concept.name = conceptStrings[concept.id];
|
||
concept.url = conceptBaseUrl + '#' + concept.id;
|
||
if(!concept.language) { concept.language = 'all'; }
|
||
conceptList.push(concept);
|
||
}
|
||
return conceptList;
|
||
}
|
||
|
||
var boardDefinitions = [
|
||
{
|
||
name: "grovepi",
|
||
friendlyName: strings.messages.grovehat,
|
||
image: "grovepihat.png",
|
||
adc: "grovepi",
|
||
portTypes: {
|
||
"D": [5, 16, 18, 22, 24, 26],
|
||
"A": [0, 2, 4, 6],
|
||
"i2c": ["i2c"],
|
||
},
|
||
default: [
|
||
{ type: "screen", suggestedName: strings.messages.sensorNameScreen + "1", port: "i2c", subType: "16x2lcd" },
|
||
{ type: "led", suggestedName: strings.messages.sensorNameLed + "1", port: 'D5', subType: "blue" },
|
||
{ type: "servo", suggestedName: strings.messages.sensorNameServo + "1", port: "D16" },
|
||
{ type: "range", suggestedName: strings.messages.sensorNameDistance + "1", port :"D18", subType: "ultrasonic"},
|
||
{ type: "button", suggestedName: strings.messages.sensorNameButton + "1", port: "D22" },
|
||
{ type: "humidity", suggestedName: strings.messages.sensorNameHumidity + "1", port: "D24"},
|
||
{ type: "buzzer", suggestedName: strings.messages.sensorNameBuzzer + "1", port: "D26", subType: "active"},
|
||
{ type: "temperature", suggestedName: strings.messages.sensorNameTemperature + "1", port: 'A0', subType: "groveanalog" },
|
||
{ type: "potentiometer", suggestedName: strings.messages.sensorNamePotentiometer + "1", port :"A4"},
|
||
{ type: "light", suggestedName: strings.messages.sensorNameLight + "1", port :"A6"},
|
||
]
|
||
},
|
||
{
|
||
name: "quickpi",
|
||
friendlyName: strings.messages.quickpihat,
|
||
image: "quickpihat.png",
|
||
adc: "ads1015",
|
||
portTypes: {
|
||
"D": [5, 16, 24],
|
||
"A": [0],
|
||
},
|
||
builtinSensors: [
|
||
{ type: "screen", subType: "oled128x32", port: "i2c", suggestedName: strings.messages.sensorNameScreen + "1", },
|
||
{ type: "led", subType: "red", port: "D4", suggestedName: strings.messages.sensorNameRedLed + "1", },
|
||
{ type: "led", subType: "green", port: "D17", suggestedName: strings.messages.sensorNameGreenLed + "1", },
|
||
{ type: "led", subType: "blue", port: "D27", suggestedName: strings.messages.sensorNameBlueLed + "1", },
|
||
{ type: "irtrans", port: "D22", suggestedName: strings.messages.sensorNameIrTrans + "1", },
|
||
{ type: "irrecv", port: "D23", suggestedName: strings.messages.sensorNameIrRecv + "1", },
|
||
{ type: "sound", port: "A1", suggestedName: strings.messages.sensorNameMicrophone + "1", },
|
||
{ type: "buzzer", subType: "passive", port: "D12", suggestedName: strings.messages.sensorNameBuzzer + "1", },
|
||
{ type: "accelerometer", subType: "BMI160", port: "i2c", suggestedName: strings.messages.sensorNameAccelerometer + "1", },
|
||
{ type: "gyroscope", subType: "BMI160", port: "i2c", suggestedName: strings.messages.sensorNameGyroscope + "1", },
|
||
{ type: "magnetometer", subType: "LSM303C", port: "i2c", suggestedName: strings.messages.sensorNameMagnetometer + "1", },
|
||
{ type: "temperature", subType: "BMI160", port: "i2c", suggestedName: strings.messages.sensorNameTemperature + "1", },
|
||
{ type: "range", subType: "vl53l0x", port: "i2c", suggestedName: strings.messages.sensorNameDistance + "1", },
|
||
{ type: "button", port: "D26", suggestedName: strings.messages.sensorNameButton + "1", },
|
||
{ type: "light", port: "A2", suggestedName: strings.messages.sensorNameLight + "1", },
|
||
{ type: "stick", port: "D7", suggestedName: strings.messages.sensorNameStick + "1", }
|
||
],
|
||
},
|
||
{
|
||
name: "pinohat",
|
||
image: "pinohat.png",
|
||
friendlyName: strings.messages.pinohat,
|
||
adc: ["ads1015", "none"],
|
||
portTypes: {
|
||
"D": [5, 16, 24],
|
||
"A": [0],
|
||
"i2c": ["i2c"],
|
||
},
|
||
}
|
||
]
|
||
|
||
|
||
var sensorDefinitions = [
|
||
/******************************** */
|
||
/* Actuators */
|
||
/**********************************/
|
||
{
|
||
name: "led",
|
||
suggestedName: strings.messages.sensorNameLed,
|
||
description: strings.messages.led,
|
||
isAnalog: false,
|
||
isSensor: false,
|
||
portType: "D",
|
||
getInitialState: function (sensor) {
|
||
return false;
|
||
},
|
||
selectorImages: ["ledon-red.png"],
|
||
valueType: "boolean",
|
||
pluggable: true,
|
||
getPercentageFromState: function (state) {
|
||
if (state)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
if (percentage)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
setLiveState: function (sensor, state, callback) {
|
||
var ledstate = state ? 1 : 0;
|
||
var command = "setLedState(\"" + sensor.name + "\"," + ledstate + ")";
|
||
|
||
context.quickPiConnection.sendCommand(command, callback);
|
||
},
|
||
getStateString: function(state) {
|
||
return state ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase();
|
||
},
|
||
subTypes: [{
|
||
subType: "blue",
|
||
description: strings.messages.blueled,
|
||
selectorImages: ["ledon-blue.png"],
|
||
suggestedName: strings.messages.sensorNameBlueLed,
|
||
},
|
||
{
|
||
subType: "green",
|
||
description: strings.messages.greenled,
|
||
selectorImages: ["ledon-green.png"],
|
||
suggestedName: strings.messages.sensorNameGreenLed,
|
||
},
|
||
{
|
||
subType: "orange",
|
||
description: strings.messages.orangeled,
|
||
selectorImages: ["ledon-orange.png"],
|
||
suggestedName: strings.messages.sensorNameOrangeLed,
|
||
},
|
||
{
|
||
subType: "red",
|
||
description: strings.messages.redled,
|
||
selectorImages: ["ledon-red.png"],
|
||
suggestedName: strings.messages.sensorNameRedLed,
|
||
}
|
||
],
|
||
},
|
||
{
|
||
name: "buzzer",
|
||
suggestedName: strings.messages.sensorNameBuzzer,
|
||
description: strings.messages.buzzer,
|
||
isAnalog: false,
|
||
isSensor: false,
|
||
getInitialState: function(sensor) {
|
||
return false;
|
||
},
|
||
portType: "D",
|
||
selectorImages: ["buzzer-ringing.png"],
|
||
valueType: "boolean",
|
||
getPercentageFromState: function (state, sensor) {
|
||
|
||
if (sensor.showAsAnalog)
|
||
{
|
||
return (state - sensor.minAnalog) / (sensor.maxAnalog - sensor.minAnalog);
|
||
} else {
|
||
if (state)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
}
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
if (percentage)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
setLiveState: function (sensor, state, callback) {
|
||
var ledstate = state ? 1 : 0;
|
||
var command = "setBuzzerState(\"" + sensor.name + "\"," + ledstate + ")";
|
||
|
||
context.quickPiConnection.sendCommand(command, callback);
|
||
},
|
||
getStateString: function(state) {
|
||
|
||
if(typeof state == 'number' &&
|
||
state != 1 &&
|
||
state != 0) {
|
||
|
||
return state.toString() + "Hz";
|
||
}
|
||
return state ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase();
|
||
},
|
||
subTypes: [{
|
||
subType: "active",
|
||
description: strings.messages.grovebuzzer,
|
||
pluggable: true,
|
||
},
|
||
{
|
||
subType: "passive",
|
||
description: strings.messages.quickpibuzzer,
|
||
}],
|
||
},
|
||
{
|
||
name: "servo",
|
||
suggestedName: strings.messages.sensorNameServo,
|
||
description: strings.messages.servo,
|
||
isAnalog: true,
|
||
isSensor: false,
|
||
getInitialState: function(sensor) {
|
||
return 0;
|
||
},
|
||
portType: "D",
|
||
valueType: "number",
|
||
pluggable: true,
|
||
valueMin: 0,
|
||
valueMax: 180,
|
||
selectorImages: ["servo.png", "servo-pale.png", "servo-center.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 180;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 180);
|
||
},
|
||
setLiveState: function (sensor, state, callback) {
|
||
var command = "setServoAngle(\"" + sensor.name + "\"," + state + ")";
|
||
|
||
context.quickPiConnection.sendCommand(command, callback);
|
||
},
|
||
getStateString: function(state) {
|
||
return "" + state + "°";
|
||
}
|
||
},
|
||
{
|
||
name: "screen",
|
||
suggestedName: strings.messages.sensorNameScreen,
|
||
description: strings.messages.screen,
|
||
isAnalog: false,
|
||
isSensor: false,
|
||
getInitialState: function(sensor) {
|
||
if (sensor.isDrawingScreen)
|
||
return null;
|
||
else
|
||
return {line1: "", line2: ""};
|
||
},
|
||
cellsAmount: function(paper) {
|
||
if(context.board == 'grovepi') {
|
||
return 2;
|
||
}
|
||
if(paper.width < 250) {
|
||
return 4;
|
||
} else if(paper.width < 350) {
|
||
return 3;
|
||
}
|
||
|
||
if (context.compactLayout)
|
||
return 3;
|
||
else
|
||
return 2;
|
||
},
|
||
portType: "i2c",
|
||
valueType: "object",
|
||
selectorImages: ["screen.png"],
|
||
compareState: function (state1, state2) {
|
||
// Both are null are equal
|
||
if (state1 == null && state2 == null)
|
||
return true;
|
||
|
||
// If only one is null they are different
|
||
if ((state1 == null && state2) ||
|
||
(state1 && state2 == null))
|
||
return false;
|
||
|
||
if (state1.isDrawingData !=
|
||
state2.isDrawingData)
|
||
return false;
|
||
|
||
if (state1 && state1.isDrawingData) {
|
||
// They are ImageData objects
|
||
// The image data is RGBA so there are 4 bits per pixel
|
||
|
||
var data1 = state1.getData(1).data;
|
||
var data2 = state2.getData(1).data;
|
||
|
||
for (var i = 0; i < data1.length; i+=4) {
|
||
if (data1[i] != data2[i] ||
|
||
data1[i + 1] != data2[i + 1] ||
|
||
data1[i + 2] != data2[i + 2] ||
|
||
data1[i + 3] != data2[i + 3])
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
} else {
|
||
|
||
// Otherwise compare the strings
|
||
return (state1.line1 == state2.line1) &&
|
||
((state1.line2 == state2.line2) ||
|
||
(!state1.line2 && !state2.line2));
|
||
}
|
||
},
|
||
setLiveState: function (sensor, state, callback) {
|
||
var line2 = state.line2;
|
||
if (!line2)
|
||
line2 = "";
|
||
|
||
var command = "displayText(\"" + sensor.name + "\"," + state.line1 + "\", \"" + line2 + "\")";
|
||
|
||
context.quickPiConnection.sendCommand(command, callback);
|
||
},
|
||
getStateString: function(state) {
|
||
if(!state) { return '""'; }
|
||
|
||
if (state.isDrawingData)
|
||
return strings.messages.drawing;
|
||
else
|
||
return '"' + state.line1 + (state.line2 ? " / " + state.line2 : "") + '"';
|
||
},
|
||
getWrongStateString: function(failInfo) {
|
||
if(!failInfo.expected ||
|
||
!failInfo.expected.isDrawingData ||
|
||
!failInfo.actual ||
|
||
!failInfo.actual.isDrawingData) {
|
||
return null; // Use default message
|
||
}
|
||
var data1 = failInfo.expected.getData(1).data;
|
||
var data2 = failInfo.actual.getData(1).data;
|
||
var nbDiff = 0;
|
||
for (var i = 0; i < data1.length; i+=4) {
|
||
if(data1[i] != data2[i]) {
|
||
nbDiff += 1;
|
||
}
|
||
}
|
||
return strings.messages.wrongStateDrawing.format(failInfo.name, nbDiff, failInfo.time);
|
||
},
|
||
subTypes: [{
|
||
subType: "16x2lcd",
|
||
description: strings.messages.grove16x2lcd,
|
||
pluggable: true,
|
||
},
|
||
{
|
||
subType: "oled128x32",
|
||
description: strings.messages.oled128x32,
|
||
}],
|
||
|
||
},
|
||
{
|
||
name: "irtrans",
|
||
suggestedName: strings.messages.sensorNameIrTrans,
|
||
description: strings.messages.irtrans,
|
||
isAnalog: false,
|
||
isSensor: true,
|
||
portType: "D",
|
||
valueType: "number",
|
||
valueMin: 0,
|
||
valueMax: 60,
|
||
selectorImages: ["irtranson.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 60;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 60);
|
||
},
|
||
setLiveState: function (sensor, state, callback) {
|
||
var ledstate = state ? 1 : 0;
|
||
var command = "setInfraredState(\"" + sensor.name + "\"," + ledstate + ")";
|
||
|
||
context.quickPiConnection.sendCommand(command, callback);
|
||
},
|
||
},
|
||
/******************************** */
|
||
/* sensors */
|
||
/**********************************/
|
||
{
|
||
name: "button",
|
||
suggestedName: strings.messages.sensorNameButton,
|
||
description: strings.messages.button,
|
||
isAnalog: false,
|
||
isSensor: true,
|
||
portType: "D",
|
||
valueType: "boolean",
|
||
pluggable: true,
|
||
selectorImages: ["buttonoff.png"],
|
||
getPercentageFromState: function (state) {
|
||
if (state)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
if (percentage)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("isButtonPressed(\"" + sensor.name + "\")", function (retVal) {
|
||
var intVal = parseInt(retVal, 10);
|
||
callback(intVal != 0);
|
||
});
|
||
},
|
||
},
|
||
{
|
||
name: "stick",
|
||
suggestedName: strings.messages.sensorNameStick,
|
||
description: strings.messages.fivewaybutton,
|
||
isAnalog: false,
|
||
isSensor: true,
|
||
portType: "D",
|
||
valueType: "boolean",
|
||
selectorImages: ["stick.png"],
|
||
gpiosNames: ["up", "down", "left", "right", "center"],
|
||
gpios: [10, 9, 11, 8, 7],
|
||
getPercentageFromState: function (state) {
|
||
if (state)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
if (percentage)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
},
|
||
compareState: function (state1, state2) {
|
||
if (state1 == null && state2 == null)
|
||
return true;
|
||
|
||
return state1[0] == state2[0] &&
|
||
state1[1] == state2[1] &&
|
||
state1[2] == state2[2] &&
|
||
state1[3] == state2[3] &&
|
||
state1[4] == state2[4];
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
var cmd = "readStick(" + this.gpios.join() + ")";
|
||
|
||
context.quickPiConnection.sendCommand("readStick(" + this.gpios.join() + ")", function (retVal) {
|
||
var array = JSON.parse(retVal);
|
||
callback(array);
|
||
});
|
||
},
|
||
getButtonState: function(buttonname, state) {
|
||
if (state) {
|
||
var buttonparts = buttonname.split(".");
|
||
var actualbuttonmame = buttonname;
|
||
if (buttonparts.length == 2) {
|
||
actualbuttonmame = buttonparts[1];
|
||
}
|
||
|
||
var index = this.gpiosNames.indexOf(actualbuttonmame);
|
||
|
||
if (index >= 0) {
|
||
return state[index];
|
||
}
|
||
}
|
||
|
||
return false;
|
||
},
|
||
cellsAmount: function(paper) {
|
||
return 2;
|
||
},
|
||
},
|
||
{
|
||
name: "temperature",
|
||
suggestedName: strings.messages.sensorNameTemperature,
|
||
description: strings.messages.tempsensor,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "A",
|
||
valueType: "number",
|
||
valueMin: 0,
|
||
valueMax: 60,
|
||
selectorImages: ["temperature-hot.png", "temperature-overlay.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 60;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 60);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readTemperature(\"" + sensor.name + "\")", function(val) {
|
||
val = Math.round(val);
|
||
callback(val);
|
||
});
|
||
},
|
||
subTypes: [{
|
||
subType: "groveanalog",
|
||
description: strings.messages.groveanalogtempsensor,
|
||
portType: "A",
|
||
pluggable: true,
|
||
},
|
||
{
|
||
subType: "BMI160",
|
||
description: strings.messages.quickpigyrotempsensor,
|
||
portType: "i2c",
|
||
},
|
||
{
|
||
subType: "DHT11",
|
||
description: strings.messages.dht11tempsensor,
|
||
portType: "D",
|
||
pluggable: true,
|
||
}],
|
||
},
|
||
{
|
||
name: "potentiometer",
|
||
suggestedName: strings.messages.sensorNamePotentiometer,
|
||
description: strings.messages.potentiometer,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "A",
|
||
valueType: "number",
|
||
pluggable: true,
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
selectorImages: ["potentiometer.png", "potentiometer-pale.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 100;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 100);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readRotaryAngle(\"" + sensor.name + "\")", function(val) {
|
||
val = Math.round(val);
|
||
callback(val);
|
||
});
|
||
},
|
||
},
|
||
{
|
||
name: "light",
|
||
suggestedName: strings.messages.sensorNameLight,
|
||
description: strings.messages.lightsensor,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "A",
|
||
valueType: "number",
|
||
pluggable: true,
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
selectorImages: ["light.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 100;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 100);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readLightIntensity(\"" + sensor.name + "\")", function(val) {
|
||
val = Math.round(val);
|
||
callback(val);
|
||
});
|
||
},
|
||
},
|
||
{
|
||
name: "range",
|
||
suggestedName: strings.messages.sensorNameDistance,
|
||
description: strings.messages.distancesensor,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "D",
|
||
valueType: "number",
|
||
valueMin: 0,
|
||
valueMax: 5000,
|
||
selectorImages: ["range.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 500;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 500);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readDistance(\"" + sensor.name + "\")", function(val) {
|
||
val = Math.round(val);
|
||
callback(val);
|
||
});
|
||
},
|
||
subTypes: [{
|
||
subType: "vl53l0x",
|
||
description: strings.messages.timeofflightranger,
|
||
portType: "i2c",
|
||
},
|
||
{
|
||
subType: "ultrasonic",
|
||
description: strings.messages.ultrasonicranger,
|
||
portType: "D",
|
||
pluggable: true,
|
||
}],
|
||
|
||
},
|
||
{
|
||
name: "humidity",
|
||
suggestedName: strings.messages.sensorNameHumidity,
|
||
description: strings.messages.humiditysensor,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "D",
|
||
valueType: "number",
|
||
pluggable: true,
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
selectorImages: ["humidity.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 100;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 100);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readHumidity(\"" + sensor.name + "\")", function(val) {
|
||
val = Math.round(val);
|
||
callback(val);
|
||
});
|
||
},
|
||
},
|
||
{
|
||
name: "sound",
|
||
suggestedName: strings.messages.sensorNameMicrophone,
|
||
description: strings.messages.soundsensor,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "A",
|
||
valueType: "number",
|
||
pluggable: true,
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
selectorImages: ["sound.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 100;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 100);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readSoundLevel(\"" + sensor.name + "\")", function(val) {
|
||
val = Math.round(val);
|
||
callback(val);
|
||
});
|
||
},
|
||
},
|
||
{
|
||
name: "accelerometer",
|
||
suggestedName: strings.messages.sensorNameAccelerometer,
|
||
description: strings.messages.accelerometerbmi160,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "i2c",
|
||
valueType: "object",
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
step: 0.1,
|
||
selectorImages: ["accel.png"],
|
||
getStateString: function (state) {
|
||
if (state == null)
|
||
return "0m/s²";
|
||
|
||
if (Array.isArray(state))
|
||
{
|
||
return "X: " + state[0] + "m/s² Y: " + state[1] + "m/s² Z: " + state[2] + "m/s²";
|
||
}
|
||
else {
|
||
return state.toString() + "m/s²";
|
||
}
|
||
},
|
||
getPercentageFromState: function (state) {
|
||
return ((state + 78.48) / 156.96);
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
var value = ((percentage * 156.96) - 78.48);
|
||
return parseFloat(value.toFixed(1));
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readAccelBMI160()", function(val) {
|
||
var array = JSON.parse(val);
|
||
callback(array);
|
||
});
|
||
},
|
||
cellsAmount: function(paper) {
|
||
return 2;
|
||
},
|
||
},
|
||
{
|
||
name: "gyroscope",
|
||
suggestedName: strings.messages.sensorNameGyroscope,
|
||
description: strings.messages.gyrobmi160,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "i2c",
|
||
valueType: "object",
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
selectorImages: ["gyro.png"],
|
||
getPercentageFromState: function (state) {
|
||
return (state + 125) / 250;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 250) - 125;
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readGyroBMI160()", function(val) {
|
||
|
||
var array = JSON.parse(val);
|
||
array[0] = Math.round(array[0]);
|
||
array[1] = Math.round(array[1]);
|
||
array[2] = Math.round(array[2]);
|
||
callback(array);
|
||
});
|
||
},
|
||
cellsAmount: function(paper) {
|
||
return 2;
|
||
},
|
||
},
|
||
{
|
||
name: "magnetometer",
|
||
suggestedName: strings.messages.sensorNameMagnetometer,
|
||
description: strings.messages.maglsm303c,
|
||
isAnalog: true,
|
||
isSensor: true,
|
||
portType: "i2c",
|
||
valueType: "object",
|
||
valueMin: 0,
|
||
valueMax: 100,
|
||
selectorImages: ["mag.png"],
|
||
getPercentageFromState: function (state) {
|
||
return (state + 1600) / 3200;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 3200) - 1600;
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("readMagnetometerLSM303C(False)", function(val) {
|
||
|
||
var array = JSON.parse(val);
|
||
|
||
array[0] = Math.round(array[0]);
|
||
array[1] = Math.round(array[1]);
|
||
array[2] = Math.round(array[2]);
|
||
|
||
callback(array);
|
||
});
|
||
},
|
||
cellsAmount: function(paper) {
|
||
return 2;
|
||
},
|
||
},
|
||
{
|
||
name: "irrecv",
|
||
suggestedName: strings.messages.sensorNameIrRecv,
|
||
description: strings.messages.irreceiver,
|
||
isAnalog: false,
|
||
isSensor: true,
|
||
portType: "D",
|
||
valueType: "number",
|
||
valueMin: 0,
|
||
valueMax: 60,
|
||
selectorImages: ["irrecvon.png"],
|
||
getPercentageFromState: function (state) {
|
||
return state / 60;
|
||
},
|
||
getStateFromPercentage: function (percentage) {
|
||
return Math.round(percentage * 60);
|
||
},
|
||
getLiveState: function (sensor, callback) {
|
||
context.quickPiConnection.sendCommand("isButtonPressed(\"" + sensor.name + "\")", function (retVal) {
|
||
var intVal = parseInt(retVal, 10);
|
||
callback(intVal == 0);
|
||
});
|
||
},
|
||
},
|
||
/******************************** */
|
||
/* dummy sensors */
|
||
/**********************************/
|
||
{
|
||
name: "cloudstore",
|
||
suggestedName: strings.messages.sensorNameCloudStore,
|
||
description: strings.messages.cloudstore,
|
||
isAnalog: false,
|
||
isSensor: false,
|
||
portType: "none",
|
||
valueType: "object",
|
||
selectorImages: ["cloudstore.png"],
|
||
/*getInitialState: function(sensor) {
|
||
return {};
|
||
},*/
|
||
|
||
getWrongStateString: function(failInfo) {
|
||
/**
|
||
* Call this function when more.length > less.length. It will find the key that is missing inside of the
|
||
* less array
|
||
* @param more The bigger array, containing one or more key more than less
|
||
* @param less Less, the smaller array, he has a key or more missing
|
||
*/
|
||
function getMissingKey(more, less) {
|
||
for (var i = 0; i < more.length; i++) {
|
||
var found = false;
|
||
for (var j = 0; j < less.length; j++) {
|
||
if (more[i] === less[j]) {
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!found)
|
||
return more[i];
|
||
}
|
||
// should never happen because length are different.
|
||
return null;
|
||
}
|
||
|
||
// the type of a value in comparison.
|
||
var valueType = {
|
||
// Primitive type are strings and integers
|
||
PRIMITIVE: "primitive",
|
||
ARRAY: "array",
|
||
DICTIONARY: "dictionary",
|
||
// if two values are of wrong type then this is returned
|
||
WRONG_TYPE: "wrong_type"
|
||
};
|
||
|
||
/**
|
||
* This method allow us to compare two keys of the cloud and their values
|
||
* @param actual The actual key that we have
|
||
* @param expected The expected key that we have
|
||
* @return An object containing the type of the return and the key that differ
|
||
*/
|
||
function compareKeys(actual, expected) {
|
||
function compareArrays(arr1, arr2) {
|
||
if (arr1.length != arr2.length)
|
||
return false;
|
||
for (var i = 0; i < arr1.length; i++) {
|
||
for (var j = 0; j < arr2.length; j++) {
|
||
if (arr1[i] !== arr2[i])
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
var actualKeys = Object.keys(actual);
|
||
|
||
for (var i = 0; i < actualKeys.length; i++) {
|
||
var actualVal = actual[actualKeys[i]];
|
||
|
||
// they both have the same keys so we can do that.
|
||
var expectedVal = expected[actualKeys[i]];
|
||
|
||
if (isPrimitive(expectedVal)) {
|
||
// if string with int for example
|
||
if (typeof expectedVal !== typeof actualVal) {
|
||
return {
|
||
type: valueType.WRONG_TYPE,
|
||
key: actualKeys[i]
|
||
}
|
||
}
|
||
if (expectedVal !== actualVal) {
|
||
return {
|
||
type: valueType.PRIMITIVE,
|
||
key: actualKeys[i]
|
||
};
|
||
}
|
||
} else if (Array.isArray(expectedVal)) {
|
||
if (!Array.isArray(actualVal)) {
|
||
return {
|
||
type: valueType.WRONG_TYPE,
|
||
key: actualKeys[i]
|
||
};
|
||
}
|
||
if (!compareArrays(expectedVal, actualVal)) {
|
||
return {
|
||
type: valueType.ARRAY,
|
||
key: actualKeys[i]
|
||
};
|
||
}
|
||
// if we are in a dictionary
|
||
// method from: https://stackoverflow.com/questions/38304401/javascript-check-if-dictionary
|
||
} else if (expectedVal.constructor == Object) {
|
||
if (actualVal.constructor != Object) {
|
||
return {
|
||
type: valueType.WRONG_TYPE,
|
||
key: actualKeys[i]
|
||
};
|
||
}
|
||
if (!deepEqual(expectedVal, actualVal)) {
|
||
return {
|
||
type: valueType.DICTIONARY,
|
||
key: actualKeys[i]
|
||
};
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(!failInfo.expected &&
|
||
!failInfo.actual)
|
||
return null;
|
||
|
||
var expected = failInfo.expected;
|
||
var actual = failInfo.actual;
|
||
|
||
var expectedKeys = Object.keys(expected);
|
||
var actualKeys = Object.keys(actual);
|
||
|
||
if (expectedKeys.length != actualKeys.length) {
|
||
if (expectedKeys.length > actualKeys.length) {
|
||
var missingKey = getMissingKey(expectedKeys, actualKeys);
|
||
return strings.messages.cloudMissingKey.format(missingKey);
|
||
} else {
|
||
var additionalKey = getMissingKey(actualKeys, expectedKeys);
|
||
return strings.messages.cloudMoreKey.format(additionalKey);
|
||
}
|
||
}
|
||
|
||
// This will return a key that is missing inside of expectedKeys if there is one, otherwise it will return null.
|
||
var unexpectedKey = getMissingKey(actualKeys, expectedKeys);
|
||
|
||
if (unexpectedKey) {
|
||
return strings.messages.cloudUnexpectedKeyCorrection.format(unexpectedKey);
|
||
}
|
||
|
||
var keyCompare = compareKeys(actual, expected);
|
||
|
||
switch (keyCompare.type) {
|
||
case valueType.PRIMITIVE:
|
||
return strings.messages.cloudPrimitiveWrongKey.format(keyCompare.key, expected[keyCompare.key], actual[keyCompare.key]);
|
||
case valueType.WRONG_TYPE:
|
||
var typeActual = typeof actual[keyCompare.key];
|
||
var typeExpected = typeof expected[keyCompare.key];
|
||
// we need to check if it is an array or a dictionary
|
||
if (typeActual == "object") {
|
||
if (Array.isArray(actual[keyCompare.key]))
|
||
typeActual = "array";
|
||
}
|
||
if (typeExpected == "object") {
|
||
if (Array.isArray(expected[keyCompare.key]))
|
||
typeExpected = "array";
|
||
}
|
||
var typeActualTranslate = quickPiLocalLanguageStrings.fr.messages.cloudTypes[typeActual];
|
||
var typeExpectedTranslate = quickPiLocalLanguageStrings.fr.messages.cloudTypes[typeExpected];
|
||
return strings.messages.cloudWrongType.format(typeActualTranslate, keyCompare.key, typeExpectedTranslate);
|
||
case valueType.ARRAY:
|
||
return strings.messages.cloudArrayWrongKey.format(keyCompare.key);
|
||
case valueType.DICTIONARY:
|
||
return strings.messages.cloudDictionaryWrongKey.format(keyCompare.key);
|
||
}
|
||
},
|
||
|
||
compareState: function (state1, state2) {
|
||
return quickPiStore.compareState(state1, state2);
|
||
}
|
||
},
|
||
{
|
||
name: "clock",
|
||
description: strings.messages.cloudstore,
|
||
isAnalog: false,
|
||
isSensor: false,
|
||
portType: "none",
|
||
valueType: "object",
|
||
selectorImages: ["clock.png"],
|
||
},
|
||
];
|
||
|
||
|
||
if(window.quickAlgoInterface) {
|
||
window.quickAlgoInterface.stepDelayMin = 1;
|
||
}
|
||
|
||
|
||
function findSensorDefinition(sensor) {
|
||
var sensorDef = null;
|
||
for (var iType = 0; iType < sensorDefinitions.length; iType++) {
|
||
var type = sensorDefinitions[iType];
|
||
|
||
if (sensor.type == type.name) {
|
||
if (sensor.subType && type.subTypes) {
|
||
|
||
for (var iSubType = 0; iSubType < type.subTypes.length; iSubType++) {
|
||
var subType = type.subTypes[iSubType];
|
||
|
||
if (subType.subType == sensor.subType) {
|
||
sensorDef = $.extend({}, type, subType);
|
||
}
|
||
}
|
||
} else {
|
||
sensorDef = type;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(sensorDef && !sensorDef.compareState) {
|
||
sensorDef.compareState = function(state1, state2) {
|
||
return state1 == state2;
|
||
};
|
||
}
|
||
|
||
return sensorDef;
|
||
}
|
||
|
||
var defaultQuickPiOptions = {
|
||
disableConnection: false,
|
||
increaseTimeAfterCalls: 5
|
||
};
|
||
function getQuickPiOption(name) {
|
||
if(name == 'disableConnection') {
|
||
// TODO :: Legacy, remove when all tasks will have been updated
|
||
return (context.infos
|
||
&& (context.infos.quickPiDisableConnection
|
||
|| (context.infos.quickPi && context.infos.quickPi.disableConnection)));
|
||
}
|
||
if(context.infos && context.infos.quickPi && typeof context.infos.quickPi[name] != 'undefined') {
|
||
return context.infos.quickPi[name];
|
||
} else {
|
||
return defaultQuickPiOptions[name];
|
||
}
|
||
}
|
||
|
||
function getWrongStateText(failInfo) {
|
||
var actualStateStr = "" + failInfo.actual;
|
||
var expectedStateStr = "" + failInfo.expected;
|
||
var sensorDef = findSensorDefinition(failInfo.sensor);
|
||
if(sensorDef) {
|
||
if(sensorDef.isSensor) {
|
||
return strings.messages.wrongStateSensor.format(failInfo.name, failInfo.time);
|
||
}
|
||
if(sensorDef.getWrongStateString) {
|
||
var sensorWrongStr = sensorDef.getWrongStateString(failInfo);
|
||
if(sensorWrongStr) {
|
||
return sensorWrongStr;
|
||
}
|
||
}
|
||
if(sensorDef.getStateString) {
|
||
actualStateStr = sensorDef.getStateString(failInfo.actual);
|
||
expectedStateStr = sensorDef.getStateString(failInfo.expected);
|
||
}
|
||
}
|
||
return strings.messages.wrongState.format(failInfo.name, actualStateStr, expectedStateStr, failInfo.time);
|
||
}
|
||
|
||
function getCurrentBoard() {
|
||
var found = boardDefinitions.find(function (element) {
|
||
if (context.board == element.name)
|
||
return element;
|
||
});
|
||
|
||
return found;
|
||
}
|
||
|
||
function getSessionStorage(name) {
|
||
// Use a try in case it gets blocked
|
||
try {
|
||
return sessionStorage[name];
|
||
} catch(e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
function setSessionStorage(name, value) {
|
||
// Use a try in case it gets blocked
|
||
try {
|
||
sessionStorage[name] = value;
|
||
} catch(e) {}
|
||
}
|
||
|
||
if(window.getQuickPiConnection) {
|
||
var lockstring = getSessionStorage('lockstring');
|
||
if(!lockstring) {
|
||
lockstring = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||
setSessionStorage('lockstring', lockstring);
|
||
}
|
||
|
||
context.quickPiConnection = getQuickPiConnection(lockstring, raspberryPiConnected, raspberryPiDisconnected, raspberryPiChangeBoard);
|
||
|
||
context.quickPiConnection.isAvailable("localhost", function(available) {
|
||
context.localhostAvailable = available;
|
||
});
|
||
|
||
context.quickPiConnection.isAvailable(window.location.hostname, function(available) {
|
||
context.windowLocationAvailable = available;
|
||
});
|
||
|
||
}
|
||
|
||
var paper;
|
||
context.offLineMode = true;
|
||
|
||
context.onExecutionEnd = function () {
|
||
if (context.autoGrading)
|
||
{
|
||
buzzerSound.stopAll();
|
||
}
|
||
|
||
};
|
||
|
||
infos.checkEndEveryTurn = true;
|
||
infos.checkEndCondition = function (context, lastTurn) {
|
||
|
||
if (!context.display && !context.autoGrading) {
|
||
context.success = true;
|
||
throw (strings.messages.manualTestSuccess);
|
||
}
|
||
|
||
if (context.failImmediately)
|
||
{
|
||
context.success = false;
|
||
throw (context.failImmediately);
|
||
}
|
||
|
||
var testEnded = lastTurn || context.currentTime > context.maxTime;
|
||
|
||
if (context.autoGrading) {
|
||
if (!testEnded) { return; }
|
||
|
||
if (lastTurn && context.display && !context.loopsForever) {
|
||
context.currentTime = Math.floor(context.maxTime * 1.05);
|
||
drawNewStateChanges();
|
||
drawCurrentTime();
|
||
}
|
||
|
||
var failInfo = null;
|
||
|
||
for(var sensorName in context.gradingStatesBySensor) {
|
||
// Cycle through each sensor from the grading states
|
||
var sensor = findSensorByName(sensorName);
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
|
||
var expectedStates = context.gradingStatesBySensor[sensorName];
|
||
if(!expectedStates.length) { continue;}
|
||
|
||
var actualStates = context.actualStatesBySensor[sensorName];
|
||
var actualIdx = 0;
|
||
|
||
// Check that we went through all expected states
|
||
for (var i = 0; i < context.gradingStatesBySensor[sensorName].length; i++) {
|
||
var expectedState = context.gradingStatesBySensor[sensorName][i];
|
||
|
||
if(expectedState.hit || expectedState.input ) { continue; } // Was hit, valid
|
||
var newFailInfo = null;
|
||
if(actualStates) {
|
||
// Scroll through actual states until we get the state at this time
|
||
while(actualIdx + 1 < actualStates.length && actualStates[actualIdx+1].time <= expectedState.time) {
|
||
actualIdx += 1;
|
||
}
|
||
if(!sensorDef.compareState(actualStates[actualIdx].state, expectedState.state)) {
|
||
newFailInfo = {
|
||
sensor: sensor,
|
||
name: sensorName,
|
||
time: expectedState.time,
|
||
expected: expectedState.state,
|
||
actual: actualStates[actualIdx].state
|
||
};
|
||
}
|
||
} else {
|
||
// No actual states to compare to
|
||
newFailInfo = {
|
||
sensor: sensor,
|
||
name: sensorName,
|
||
time: expectedState.time,
|
||
expected: expectedState.state,
|
||
actual: null
|
||
};
|
||
}
|
||
|
||
if(newFailInfo) {
|
||
// Only update failInfo if we found an error earlier
|
||
failInfo = failInfo && failInfo.time < newFailInfo.time ? failInfo : newFailInfo;
|
||
}
|
||
}
|
||
|
||
// Check that no actual state conflicts an expected state
|
||
if(!actualStates) { continue; }
|
||
var expectedIdx = 0;
|
||
for(var i = 0; i < actualStates.length ; i++) {
|
||
var actualState = actualStates[i];
|
||
while(expectedIdx + 1 < expectedStates.length && expectedStates[expectedIdx+1].time <= actualState.time) {
|
||
expectedIdx += 1;
|
||
}
|
||
if(!sensorDef.compareState(actualState.state, expectedStates[expectedIdx].state)) {
|
||
// Got an unexpected state change
|
||
var newFailInfo = {
|
||
sensor: sensor,
|
||
name: sensorName,
|
||
time: actualState.time,
|
||
expected: expectedStates[expectedIdx].state,
|
||
actual: actualState.state
|
||
};
|
||
failInfo = failInfo && failInfo.time < newFailInfo.time ? failInfo : newFailInfo;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(failInfo) {
|
||
// Missed expected state
|
||
context.success = false;
|
||
throw (getWrongStateText(failInfo));
|
||
} else {
|
||
// Success
|
||
context.success = true;
|
||
throw (strings.messages.programEnded);
|
||
}
|
||
} else {
|
||
if (!context.offLineMode) {
|
||
$('#piinstallcheck').hide();
|
||
}
|
||
|
||
if (lastTurn) {
|
||
context.success = true;
|
||
throw (strings.messages.programEnded);
|
||
}
|
||
}
|
||
};
|
||
|
||
context.generatePythonSensorTable = function()
|
||
{
|
||
var pythonSensorTable = "sensorTable = [";
|
||
var first = true;
|
||
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
if (first) {
|
||
first = false;
|
||
} else {
|
||
pythonSensorTable += ",";
|
||
}
|
||
|
||
if (sensor.type == "stick") {
|
||
var stickDefinition = findSensorDefinition(sensor);
|
||
var firststick = true;
|
||
|
||
for (var iStick = 0; iStick < stickDefinition.gpiosNames.length; iStick++) {
|
||
var name = sensor.name + "." + stickDefinition.gpiosNames[iStick];
|
||
var port = "D" + stickDefinition.gpios[iStick];
|
||
|
||
if (firststick) {
|
||
firststick = false;
|
||
} else {
|
||
pythonSensorTable += ",";
|
||
}
|
||
|
||
pythonSensorTable += "{\"type\":\"button\"";
|
||
pythonSensorTable += ",\"name\":\"" + name + "\"";
|
||
pythonSensorTable += ",\"port\":\"" + port + "\"}";
|
||
}
|
||
} else {
|
||
pythonSensorTable += "{\"type\":\"" + sensor.type + "\"";
|
||
pythonSensorTable += ",\"name\":\"" + sensor.name + "\"";
|
||
pythonSensorTable += ",\"port\":\"" + sensor.port + "\"";
|
||
if (sensor.subType)
|
||
pythonSensorTable += ",\"subType\":\"" + sensor.subType + "\"";
|
||
|
||
pythonSensorTable += "}";
|
||
}
|
||
}
|
||
|
||
var board = getCurrentBoard();
|
||
pythonSensorTable += "]; currentADC = \"" + board.adc + "\"";
|
||
|
||
return pythonSensorTable;
|
||
}
|
||
|
||
context.resetSensorTable = function()
|
||
{
|
||
var pythonSensorTable = context.generatePythonSensorTable();
|
||
|
||
context.quickPiConnection.sendCommand(pythonSensorTable, function(x) {});
|
||
}
|
||
|
||
|
||
context.findSensor = function findSensor(type, port, error=true) {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
if (sensor.type == type && sensor.port == port)
|
||
return sensor;
|
||
}
|
||
|
||
if (error) {
|
||
context.success = false;
|
||
throw (strings.messages.sensorNotFound.format('type ' + type + ', port ' + port));
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
|
||
function sensorAssignPort(sensor)
|
||
{
|
||
var board = getCurrentBoard();
|
||
var sensorDefinition = findSensorDefinition(sensor);
|
||
|
||
sensor.port = null;
|
||
|
||
// first try with built ins
|
||
if (board.builtinSensors) {
|
||
for (var i = 0; i < board.builtinSensors.length; i++) {
|
||
var builtinsensor = board.builtinSensors[i];
|
||
|
||
// Search for the specified subtype
|
||
if (builtinsensor.type == sensor.type &&
|
||
builtinsensor.subType == sensor.subType &&
|
||
!context.findSensor(builtinsensor.type, builtinsensor.port, false))
|
||
{
|
||
sensor.port = builtinsensor.port;
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Search without subtype
|
||
for (var i = 0; i < board.builtinSensors.length; i++) {
|
||
var builtinsensor = board.builtinSensors[i];
|
||
|
||
// Search for the specified subtype
|
||
if (builtinsensor.type == sensor.type &&
|
||
!context.findSensor(builtinsensor.type, builtinsensor.port, false))
|
||
{
|
||
sensor.port = builtinsensor.port;
|
||
sensor.subType = builtinsensor.subType;
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
// If this is a button try to set it to a stick
|
||
if (!sensor.port && sensor.type == "button") {
|
||
for (var i = 0; i < board.builtinSensors.length; i++) {
|
||
var builtinsensor = board.builtinSensors[i];
|
||
if (builtinsensor.type == "stick")
|
||
{
|
||
sensor.port = builtinsensor.port;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// Second try assign it a grove port
|
||
if (!sensor.port) {
|
||
var sensorDefinition = findSensorDefinition(sensor);
|
||
var pluggable = sensorDefinition.pluggable;
|
||
|
||
if (sensorDefinition.subTypes) {
|
||
for (var iSubTypes = 0; iSubTypes < sensorDefinition.subTypes.length; iSubTypes++) {
|
||
var subTypeDefinition = sensorDefinition.subTypes[iSubTypes];
|
||
if (pluggable || subTypeDefinition.pluggable) {
|
||
var ports = board.portTypes[sensorDefinition.portType];
|
||
for (var iPorts = 0; iPorts < ports.length; iPorts++) {
|
||
var port = sensorDefinition.portType;
|
||
if (sensorDefinition.portType != "i2c")
|
||
port = sensorDefinition.portType + ports[iPorts];
|
||
if (!findSensorByPort(port)) {
|
||
sensor.port = port;
|
||
|
||
if (!sensor.subType)
|
||
sensor.subType = subTypeDefinition.subType;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if (pluggable) {
|
||
var ports = board.portTypes[sensorDefinition.portType];
|
||
for (var iPorts = 0; iPorts < ports.length; iPorts++) {
|
||
var port = sensorDefinition.portType + ports[iPorts];
|
||
if (!findSensorByPort(port)) {
|
||
sensor.port = port;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
context.resetSensors = function() {
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
if (context.sensorsSaved[sensor.name] && !context.autoGrading) {
|
||
var save = context.sensorsSaved[sensor.name];
|
||
sensor.state = save.state;
|
||
sensor.screenDrawing = save.screenDrawing;
|
||
sensor.lastDrawnTime = save.lastDrawnTime;
|
||
sensor.lastDrawnState = save.lastDrawnState;
|
||
sensor.callsInTimeSlot = save.callsInTimeSlot;
|
||
sensor.lastTimeIncrease = save.lastTimeIncrease;
|
||
sensor.removed = save.removed;
|
||
sensor.quickStore = save.quickStore;
|
||
} else {
|
||
sensor.state = null;
|
||
sensor.screenDrawing = null;
|
||
sensor.lastDrawnTime = 0;
|
||
sensor.lastDrawnState = null;
|
||
sensor.callsInTimeSlot = 0;
|
||
sensor.lastTimeIncrease = 0;
|
||
sensor.removed = false;
|
||
sensor.quickStore = null;
|
||
}
|
||
if (sensor.name == "gyroscope")
|
||
sensor.rotationAngles = undefined;
|
||
}
|
||
};
|
||
|
||
context.reset = function (taskInfos) {
|
||
buzzerSound.stopAll();
|
||
|
||
context.alreadyHere = true;
|
||
|
||
context.failImmediately = null;
|
||
|
||
if (!context.offLineMode) {
|
||
$('#piinstallcheck').hide();
|
||
context.quickPiConnection.startNewSession();
|
||
context.resetSensorTable();
|
||
}
|
||
|
||
context.currentTime = 0;
|
||
if (taskInfos != undefined) {
|
||
context.actualStatesBySensor = {};
|
||
context.tickIncrease = 100;
|
||
context.autoGrading = taskInfos.autoGrading;
|
||
context.loopsForever = taskInfos.loopsForever;
|
||
context.allowInfiniteLoop = !context.autoGrading;
|
||
if (context.autoGrading) {
|
||
context.maxTime = 0;
|
||
|
||
if (taskInfos.input)
|
||
{
|
||
for (var i = 0; i < taskInfos.input.length; i++)
|
||
{
|
||
taskInfos.input[i].input = true;
|
||
}
|
||
context.gradingStatesByTime = taskInfos.input.concat(taskInfos.output);
|
||
}
|
||
else {
|
||
context.gradingStatesByTime = taskInfos.output;
|
||
}
|
||
|
||
// Copy states to avoid modifying the taskInfos states
|
||
context.gradingStatesByTime = context.gradingStatesByTime.map(
|
||
function(val) {
|
||
return Object.assign({}, val);
|
||
});
|
||
|
||
context.gradingStatesByTime.sort(function (a, b) { return a.time - b.time; });
|
||
|
||
context.gradingStatesBySensor = {};
|
||
|
||
for (var i = 0; i < context.gradingStatesByTime.length; i++) {
|
||
var state = context.gradingStatesByTime[i];
|
||
|
||
if (!context.gradingStatesBySensor.hasOwnProperty(state.name))
|
||
context.gradingStatesBySensor[state.name] = [];
|
||
|
||
context.gradingStatesBySensor[state.name].push(state);
|
||
// state.hit = false;
|
||
// state.badonce = false;
|
||
|
||
if (state.time > context.maxTime)
|
||
context.maxTime = state.time;
|
||
}
|
||
|
||
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
if (sensor.type == "buzzer") {
|
||
var states = context.gradingStatesBySensor[sensor.name];
|
||
|
||
if (states) {
|
||
for (var iState = 0; iState < states.length; iState++) {
|
||
var state = states[iState].state;
|
||
|
||
if (typeof state == 'number' &&
|
||
state != 0 &&
|
||
state != 1) {
|
||
sensor.showAsAnalog = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
var isAnalog = findSensorDefinition(sensor).isAnalog || sensor.showAsAnalog;
|
||
|
||
if (isAnalog) {
|
||
sensor.maxAnalog = Number.MIN_VALUE;
|
||
sensor.minAnalog = Number.MAX_VALUE;
|
||
|
||
if (context.gradingStatesBySensor.hasOwnProperty(sensor.name)) {
|
||
var states = context.gradingStatesBySensor[sensor.name];
|
||
|
||
for (var iState = 0; iState < states.length; iState++) {
|
||
var state = states[iState];
|
||
|
||
if (state.state > sensor.maxAnalog)
|
||
sensor.maxAnalog = state.state;
|
||
if (state.state < sensor.minAnalog)
|
||
sensor.minAnalog = state.state;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (sensor.type == "screen") {
|
||
var states = context.gradingStatesBySensor[sensor.name];
|
||
|
||
if (states) {
|
||
for (var iState = 0; iState < states.length; iState++) {
|
||
var state = states[iState];
|
||
if (state.state.isDrawingData)
|
||
sensor.isDrawingScreen = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (infos.quickPiSensors == "default")
|
||
{
|
||
infos.quickPiSensors = [];
|
||
addDefaultBoardSensors();
|
||
}
|
||
}
|
||
|
||
context.success = false;
|
||
if (context.autoGrading)
|
||
context.doNotStartGrade = false;
|
||
else
|
||
context.doNotStartGrade = true;
|
||
|
||
if (paper && context.autoGrading && context.display) {
|
||
if (context.sensorStates)
|
||
context.sensorStates.remove();
|
||
context.sensorStates = paper.set();
|
||
}
|
||
|
||
|
||
context.resetSensors();
|
||
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
// If the sensor has no port assign one
|
||
if (!sensor.port) {
|
||
sensorAssignPort(sensor);
|
||
}
|
||
}
|
||
|
||
if (context.display) {
|
||
context.recreateDisplay = true;
|
||
context.displayAutoGrading = context.autoGrading;
|
||
context.timeLineStates = [];
|
||
context.resetDisplay();
|
||
} else {
|
||
|
||
context.success = false;
|
||
}
|
||
|
||
// Needs display to be reset before calling registerQuickPiEvent
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
// Set initial state
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
if(sensorDef && !sensorDef.isSensor && sensorDef.getInitialState) {
|
||
var initialState = sensorDef.getInitialState(sensor);
|
||
if (initialState != null)
|
||
context.registerQuickPiEvent(sensor.name, initialState, true, true);
|
||
}
|
||
}
|
||
|
||
startSensorPollInterval();
|
||
};
|
||
|
||
function clearSensorPollInterval() {
|
||
if(context.sensorPollInterval) {
|
||
clearInterval(context.sensorPollInterval);
|
||
context.sensorPollInterval = null;
|
||
}
|
||
};
|
||
|
||
function startSensorPollInterval() {
|
||
// Start polling the sensors on the raspberry if the raspberry is connected
|
||
|
||
clearSensorPollInterval();
|
||
|
||
context.liveUpdateCount = 0;
|
||
|
||
if(!context.quickPiConnection.isConnected()) { return; }
|
||
|
||
context.sensorPollInterval = setInterval(function () {
|
||
if((context.runner && context.runner.isRunning())
|
||
|| context.offLineMode
|
||
|| context.liveUpdateCount != 0
|
||
|| context.stopLiveUpdate) { return; }
|
||
|
||
context.quickPiConnection.startTransaction();
|
||
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
updateLiveSensor(sensor);
|
||
}
|
||
|
||
context.quickPiConnection.endTransaction();
|
||
}, 200);
|
||
};
|
||
|
||
function updateLiveSensor(sensor) {
|
||
if (findSensorDefinition(sensor).isSensor && findSensorDefinition(sensor).getLiveState) {
|
||
context.liveUpdateCount++;
|
||
|
||
//console.log("updateLiveSensor " + sensor.name, context.liveUpdateCount);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function (returnVal) {
|
||
context.liveUpdateCount--;
|
||
|
||
//console.log("updateLiveSensor callback" + sensor.name, context.liveUpdateCount);
|
||
|
||
if (!sensor.removed) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
context.changeBoard = function(newboardname)
|
||
{
|
||
if (context.board == newboardname)
|
||
return;
|
||
|
||
var board = null;
|
||
for (var i = 0; i < boardDefinitions.length; i++) {
|
||
board = boardDefinitions[i];
|
||
|
||
if (board.name == newboardname)
|
||
break;
|
||
}
|
||
|
||
if (board == null)
|
||
return;
|
||
|
||
context.board = newboardname;
|
||
setSessionStorage('board', newboardname);
|
||
|
||
if (infos.customSensors) {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
sensor.removed = true;
|
||
}
|
||
infos.quickPiSensors = [];
|
||
|
||
if (board.builtinSensors) {
|
||
for (var i = 0; i < board.builtinSensors.length; i++) {
|
||
var sensor = board.builtinSensors[i];
|
||
|
||
var newSensor = {
|
||
"type": sensor.type,
|
||
"port": sensor.port,
|
||
"builtin": true,
|
||
};
|
||
|
||
if (sensor.subType) {
|
||
newSensor.subType = sensor.subType;
|
||
}
|
||
|
||
newSensor.name = getSensorSuggestedName(sensor.type, sensor.suggestedName);
|
||
|
||
sensor.state = null;
|
||
sensor.callsInTimeSlot = 0;
|
||
sensor.lastTimeIncrease = 0;
|
||
|
||
infos.quickPiSensors.push(newSensor);
|
||
}
|
||
}
|
||
} else {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
sensorAssignPort(sensor);
|
||
}
|
||
}
|
||
|
||
context.resetSensorTable();
|
||
context.reset();
|
||
};
|
||
|
||
|
||
|
||
context.board = "quickpi";
|
||
|
||
if (getSessionStorage('board'))
|
||
context.changeBoard(getSessionStorage('board'));
|
||
|
||
/**
|
||
* This method allow us to save the sensors inside of the variable additional.
|
||
* If other things must be saved from quickPi later, it can be saved inside of this variable.
|
||
* @param additional The additional object saved inside of the xml
|
||
*/
|
||
context.saveAdditional = function(additional) {
|
||
// we don't need to save sensors if user can't modify them
|
||
if (!infos.customSensors)
|
||
return;
|
||
|
||
additional.quickpiSensors = [];
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var currentSensor = infos.quickPiSensors[i];
|
||
var savedSensor = {
|
||
type: currentSensor.type,
|
||
port: currentSensor.port,
|
||
name: currentSensor.name
|
||
};
|
||
if (currentSensor.subType)
|
||
savedSensor.subType = currentSensor.subType;
|
||
additional.quickpiSensors.push(savedSensor);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* This function loads all additional stuff from the object "additional" for quickpi.
|
||
* For now on it only loads the sensor
|
||
* @param additional The additional variable which contains the sensors
|
||
*/
|
||
context.loadAdditional = function(additional) {
|
||
// we load sensors only if custom sensors is available
|
||
if (!infos.customSensors)
|
||
return;
|
||
|
||
var newSensors = additional.quickpiSensors;
|
||
|
||
// we don't verify if sensors are empty or not, because if they are it is maybe meant this
|
||
// way by the user
|
||
if (!newSensors)
|
||
return;
|
||
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
sensor.removed = true;
|
||
}
|
||
|
||
infos.quickPiSensors = [];
|
||
|
||
for (var i = 0; i < newSensors.length; i++) {
|
||
var sensor = {
|
||
type: newSensors[i].type,
|
||
port: newSensors[i].port,
|
||
name: newSensors[i].name
|
||
};
|
||
|
||
if (newSensors[i].subType)
|
||
sensor.sybType = newSensors[i].subType;
|
||
|
||
sensor.state = null;
|
||
sensor.callsInTimeSlot = 0;
|
||
sensor.lastTimeIncrease = 0;
|
||
|
||
infos.quickPiSensors.push(sensor);
|
||
}
|
||
|
||
context.recreateDisplay = true;
|
||
this.resetDisplay();
|
||
};
|
||
|
||
context.resetDisplay = function() {
|
||
if (!context.display || !this.raphaelFactory)
|
||
return;
|
||
|
||
|
||
context.autoGrading = context.displayAutoGrading;
|
||
|
||
if (context.recreateDisplay || !paper)
|
||
{
|
||
context.createDisplay();
|
||
context.recreateDisplay = false;
|
||
}
|
||
|
||
paper.setSize(($('#virtualSensors').width() * context.quickPiZoom), $('#virtualSensors').height());
|
||
|
||
var area = paper.width * paper.height;
|
||
context.compactLayout = false;
|
||
if (area < 218700)
|
||
{
|
||
context.compactLayout = true;
|
||
}
|
||
|
||
if (context.sensorDivisions) {
|
||
context.sensorDivisions.remove();
|
||
}
|
||
|
||
context.sensorDivisions = paper.set();
|
||
|
||
// Fix this so we don't have to recreate this.
|
||
if (context.timeLineCurrent)
|
||
{
|
||
context.timeLineCurrent.remove();
|
||
context.timeLineCurrent = null;
|
||
}
|
||
|
||
if (context.timeLineCircle)
|
||
{
|
||
context.timeLineCircle.remove();
|
||
context.timeLineCircle = null;
|
||
}
|
||
|
||
if (context.timeLineTriangle) {
|
||
context.timeLineTriangle.remove();
|
||
context.timeLineTriangle = null;
|
||
}
|
||
|
||
if (context.autoGrading) {
|
||
if (context.sensorStates)
|
||
context.sensorStates.remove();
|
||
context.sensorStates = paper.set();
|
||
//paper.clear(); // Do this for now.
|
||
|
||
var numSensors = infos.quickPiSensors.length;
|
||
var sensorSize = Math.min(paper.height / numSensors * 0.80, $('#virtualSensors').width() / 10);
|
||
|
||
//var sensorSize = Math.min(paper.height / (numSensors + 1));
|
||
|
||
|
||
context.timeLineSlotHeight = Math.min(paper.height / (numSensors + 1));
|
||
context.sensorSize = sensorSize * .90;
|
||
|
||
context.timelineStartx = context.sensorSize * 3;
|
||
|
||
var maxTime = context.maxTime;
|
||
if (maxTime == 0)
|
||
maxTime = 1000;
|
||
|
||
if (!context.loopsForever)
|
||
maxTime = Math.floor(maxTime * 1.05);
|
||
|
||
context.pixelsPerTime = (paper.width - context.timelineStartx - 30) / maxTime;
|
||
|
||
context.timeLineY = 25 + (context.timeLineSlotHeight * (infos.quickPiSensors.length));
|
||
|
||
|
||
var color = true;
|
||
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
sensor.drawInfo = {
|
||
x: 0,
|
||
y: 10 + (context.timeLineSlotHeight * iSensor),
|
||
width: sensorSize * .90,
|
||
height: sensorSize * .90
|
||
};
|
||
|
||
var rect = paper.rect(0, sensor.drawInfo.y, paper.width, context.timeLineSlotHeight);
|
||
|
||
rect.attr({
|
||
"fill": color ? "#0000FF" : "#00FF00",
|
||
"stroke": "none",
|
||
"opacity": 0.03,
|
||
});
|
||
context.sensorDivisions.push(rect);
|
||
color = !color;
|
||
}
|
||
|
||
drawTimeLine();
|
||
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
drawSensor(sensor);
|
||
sensor.timelinelastxlabel = 0;
|
||
|
||
if (context.gradingStatesBySensor.hasOwnProperty(sensor.name)) {
|
||
var states = context.gradingStatesBySensor[sensor.name];
|
||
var startTime = 0;
|
||
var lastState = null;
|
||
sensor.lastAnalogState = null;
|
||
|
||
for (var iState = 0; iState < states.length; iState++) {
|
||
var state = states[iState];
|
||
|
||
drawSensorTimeLineState(sensor, lastState, startTime, state.time, "expected", true);
|
||
|
||
startTime = state.time;
|
||
lastState = state.state;
|
||
}
|
||
|
||
drawSensorTimeLineState(sensor, lastState, state.time, context.maxTime, "expected", true);
|
||
|
||
if (!context.loopsForever)
|
||
drawSensorTimeLineState(sensor, lastState, startTime, maxTime, "finnish", false);
|
||
|
||
sensor.lastAnalogState = null;
|
||
}
|
||
}
|
||
|
||
|
||
for (var iState = 0; iState < context.timeLineStates.length; iState++) {
|
||
var timelinestate = context.timeLineStates[iState];
|
||
|
||
drawSensorTimeLineState(timelinestate.sensor,
|
||
timelinestate.state,
|
||
timelinestate.startTime,
|
||
timelinestate.endTime,
|
||
timelinestate.type,
|
||
true);
|
||
}
|
||
} else {
|
||
var nSensors = infos.quickPiSensors.length;
|
||
|
||
infos.quickPiSensors.forEach(function (sensor) {
|
||
var cellsAmount = findSensorDefinition(sensor).cellsAmount;
|
||
if (cellsAmount) {
|
||
nSensors += cellsAmount(paper) - 1;
|
||
}
|
||
});
|
||
|
||
if (infos.customSensors) {
|
||
nSensors++;
|
||
}
|
||
|
||
if (nSensors < 4)
|
||
nSensors = 4;
|
||
|
||
// TODO : be carefull, the geometry is reversed for cols and rows I think
|
||
var geometry = null;
|
||
if (context.compactLayout)
|
||
geometry = squareSize(paper.width, paper.height, nSensors, 2);
|
||
else
|
||
geometry = squareSize(paper.width, paper.height, nSensors, 1);
|
||
|
||
context.sensorSize = geometry.size * .10;
|
||
|
||
var iSensor = 0;
|
||
|
||
for (var col = 0; col < geometry.cols; col++) {
|
||
var y = geometry.size * col;
|
||
|
||
var line = paper.path(["M", 0,
|
||
y,
|
||
"L", paper.width,
|
||
y]);
|
||
context.sensorDivisions.push(line);
|
||
|
||
line.attr({
|
||
"stroke-width": 1,
|
||
"stroke": "lightgrey",
|
||
"stroke-linecapstring": "round"
|
||
});
|
||
|
||
for (var row = 0; row < geometry.rows; row++) {
|
||
var x = paper.width / geometry.rows * row;
|
||
var y1 = y + geometry.size / 4;
|
||
var y2 = y + geometry.size * 3 / 4;
|
||
var cells = 1;
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
var foundsize = 0;
|
||
|
||
var cellsAmount = null;
|
||
if (sensor)
|
||
cellsAmount = findSensorDefinition(sensor).cellsAmount;
|
||
|
||
if (cellsAmount)
|
||
cells = cellsAmount(paper);
|
||
|
||
// Particular case if we have a screen and only 2 columns, we can put the
|
||
// cells of the screen at 2 because the display is still good with it.
|
||
// I used rows, because I think that for geometry, rows and cols are reversed. You can try to change
|
||
// it and see the result in animal connecte.
|
||
if (sensor && sensor.type === "screen" && cells > geometry.rows && cells == 3 && geometry.rows == 2)
|
||
cells = 2;
|
||
|
||
line = paper.path(["M", x,
|
||
y1,
|
||
"L", x,
|
||
y2]);
|
||
context.sensorDivisions.push(line);
|
||
|
||
line.attr({
|
||
"stroke-width": 1,
|
||
"stroke": "lightgrey",
|
||
"stroke-linecapstring": "round"
|
||
});
|
||
|
||
var foundrows = false;
|
||
var bump = false;
|
||
|
||
while (!foundrows && !bump)
|
||
{
|
||
var rowsleft = geometry.rows - row;
|
||
if (cells > rowsleft)
|
||
{
|
||
for (var iNewSensor = iSensor + 1; iNewSensor < infos.quickPiSensors.length; iNewSensor++)
|
||
{
|
||
var newSensor = infos.quickPiSensors[iNewSensor];
|
||
|
||
cells = 1;
|
||
cellsAmount = findSensorDefinition(newSensor).cellsAmount;
|
||
|
||
if (cellsAmount)
|
||
cells = cellsAmount(paper);
|
||
|
||
if (cells == 1)
|
||
{
|
||
infos.quickPiSensors[iNewSensor] = sensor;
|
||
infos.quickPiSensors[iSensor] = newSensor;
|
||
sensor = newSensor;
|
||
foundrows = true;
|
||
break;
|
||
}
|
||
}
|
||
bump = true;
|
||
}
|
||
else
|
||
{
|
||
foundrows = true;
|
||
}
|
||
}
|
||
|
||
if (bump)
|
||
continue;
|
||
|
||
|
||
if (iSensor == infos.quickPiSensors.length && infos.customSensors) {
|
||
drawCustomSensorAdder(x, y, geometry.size);
|
||
} else if (infos.quickPiSensors[iSensor]) {
|
||
row += cells - 1;
|
||
|
||
sensor.drawInfo = {
|
||
x: x,
|
||
y: y,
|
||
width: (paper.width / geometry.rows) * cells,
|
||
height: geometry.size
|
||
}
|
||
|
||
drawSensor(sensor);
|
||
}
|
||
iSensor++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Reset the context's display
|
||
context.createDisplay = function () {
|
||
// Do something here
|
||
//$('#grid').html('Display for the library goes here.');
|
||
|
||
// Ask the parent to update sizes
|
||
//context.blocklyHelper.updateSize();
|
||
//context.updateScale();
|
||
|
||
if (!context.display || !this.raphaelFactory)
|
||
return;
|
||
|
||
|
||
var connectionHTML = "<div id=\"piui\">" +
|
||
" <button type=\"button\" id=\"piconnect\" class=\"btn\">" +
|
||
" <span class=\"fa fa-wifi\"></span><span id=\"piconnecttext\" class=\"btnText\">" + strings.messages.connect + "</span> <span id=\"piconnectprogress\" class=\"fas fa-spinner fa-spin\"></span>" +
|
||
" </button>" +
|
||
" <span id=\"piinstallui\">" +
|
||
" <span class=\"fa fa-exchange-alt\"></span>" +
|
||
" <button type=\"button\" id=\"piinstall\" class=\"btn\">" +
|
||
" <span class=\"fa fa-upload\"></span><span>" + strings.messages.install + "</span><span id=piinstallprogresss class=\"fas fa-spinner fa-spin\"></span><span id=\"piinstallcheck\" class=\"fa fa-check\"></span>" +
|
||
" </button>" +
|
||
" </span>" +
|
||
" <span id=\"pichangehatui\">" +
|
||
" <button type=\"button\" id=\"pichangehat\" class=\"btn\">" +
|
||
" <span class=\"fas fa-hat-wizard\"></span><span>" + strings.messages.changeBoard + "</span></span></span>" +
|
||
" </button>" +
|
||
" <button type=\"button\" id=\"pihatsetup\" class=\"btn\">" +
|
||
" <span class=\"fas fa-cog\"></span><span>" + strings.messages.config + "</span></span></span>" +
|
||
" </button>" +
|
||
" </span>" +
|
||
"</div>";
|
||
|
||
var piUi = getQuickPiOption('disableConnection') ? '' : connectionHTML;
|
||
|
||
var hasIntroControls = $('#taskIntro').find('#introControls').length;
|
||
if (!hasIntroControls) {
|
||
$('#taskIntro').append("<div id=\"introControls\"></div>");
|
||
}
|
||
if (introControls === null) {
|
||
introControls = piUi + $('#introControls').html();
|
||
}
|
||
$('#introControls').html(introControls);
|
||
$('#taskIntro').addClass('piui');
|
||
|
||
$('#grid').html("<div id=\"virtualSensors\" style=\"height: 100%; width: 100%;\">"
|
||
+ "</div>");
|
||
|
||
|
||
if (!context.quickPiZoom || !context.autoGrading)
|
||
context.quickPiZoom = 1;
|
||
|
||
this.raphaelFactory.destroyAll();
|
||
paper = this.raphaelFactory.create(
|
||
"paperMain",
|
||
"virtualSensors",
|
||
($('#virtualSensors').width() * context.quickPiZoom),
|
||
$('#virtualSensors').height()
|
||
);
|
||
|
||
if (context.autoGrading) {
|
||
$('#virtualSensors').css("overflow-y", "hidden");
|
||
$('#virtualSensors').css("overflow-x", "auto");
|
||
|
||
// Allow horizontal zoom on grading
|
||
paper.canvas.onwheel = function(event) {
|
||
var originalzoom = context.quickPiZoom;
|
||
context.quickPiZoom += event.deltaY * -0.001;
|
||
|
||
if (context.quickPiZoom < 1)
|
||
context.quickPiZoom = 1;
|
||
|
||
if (originalzoom != context.quickPiZoom)
|
||
context.resetDisplay();
|
||
};
|
||
|
||
$('#virtualSensors').scroll(function(event) {
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
drawSensor(sensor);
|
||
}
|
||
});
|
||
}
|
||
else
|
||
{
|
||
$('#virtualSensors').css("overflow-y", "hidden");
|
||
$('#virtualSensors').css("overflow", "hidden");
|
||
}
|
||
|
||
|
||
if (infos.quickPiSensors == "default")
|
||
{
|
||
infos.quickPiSensors = [];
|
||
addDefaultBoardSensors();
|
||
}
|
||
|
||
context.blocklyHelper.updateSize();
|
||
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = false;
|
||
context.releasing = false;
|
||
context.offLineMode = true;
|
||
|
||
showasReleased();
|
||
|
||
if (context.quickPiConnection.isConnecting()) {
|
||
showasConnecting();
|
||
}
|
||
|
||
if (context.quickPiConnection.isConnected()) {
|
||
showasConnected();
|
||
|
||
context.offLineMode = false;
|
||
}
|
||
|
||
$('#piconnect').click(function () {
|
||
var connectionDialogHTML = "<div class=\"content connectPi qpi\">" +
|
||
" <div class=\"panel-heading\">" +
|
||
" <h2 class=\"sectionTitle\">" +
|
||
" <span class=\"iconTag\"><i class=\"icon fas fa-list-ul\"></i></span>" +
|
||
strings.messages.raspiConfig +
|
||
" </h2>" +
|
||
" <div class=\"exit\" id=\"picancel\"><i class=\"icon fas fa-times\"></i></div>" +
|
||
" </div>" +
|
||
" <div class=\"panel-body\">" +
|
||
" <div id=\"piconnectionmainui\">" +
|
||
" <div class=\"switchRadio btn-group\" id=\"piconsel\">" +
|
||
" <button type=\"button\" class=\"btn\" id=\"piconlocal\"><i class=\"fas fa-location-arrow icon\"></i>" + strings.messages.local + "</button>" +
|
||
" <button type=\"button\" class=\"btn active\" id=\"piconwifi\"><i class=\"fa fa-wifi icon\"></i>WiFi</button>" +
|
||
" <button type=\"button\" class=\"btn\" id=\"piconusb\"><i class=\"fab fa-usb icon\"></i>USB</button>" +
|
||
" <button type=\"button\" class=\"btn\" id=\"piconbt\"><i class=\"fab fa-bluetooth-b icon\"></i>Bluetooth</button>" +
|
||
" </div>" +
|
||
" <div id=\"pischoolcon\">" +
|
||
" <div class=\"form-group\">" +
|
||
" <label id=\"pischoolkeylabel\">" + strings.messages.schoolKey + "</label>" +
|
||
" <div class=\"input-group\">" +
|
||
" <div class=\"input-group-prepend\">Aa</div>" +
|
||
" <input type=\"text\" id=\"schoolkey\" class=\"form-control\">" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"form-group\">" +
|
||
" <label id=\"pilistlabel\">" + strings.messages.connectList + "</label>" +
|
||
" <div class=\"input-group\">" +
|
||
" <button class=\"input-group-prepend\" id=pigetlist disabled>" + strings.messages.getPiList + "</button>" +
|
||
" <select id=\"pilist\" class=\"custom-select\" disabled>" +
|
||
" </select>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"form-group\">" +
|
||
" <label id=\"piiplabel\">" + strings.messages.enterIpAddress + "</label>" +
|
||
" <div class=\"input-group\">" +
|
||
" <div class=\"input-group-prepend\">123</div>" +
|
||
" <input id=piaddress type=\"text\" class=\"form-control\">" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div>" +
|
||
" <input id=\"piusetunnel\" disabled type=\"checkbox\">" + strings.messages.connectTroughtTunnel +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div id=\"panel-body-usbbt\">" +
|
||
" <label id=\"piconnectionlabel\"></label>" +
|
||
" </div>" +
|
||
" <div id=\"panel-body-local\">" +
|
||
" <label id=\"piconnectionlabellocal\"></label>" +
|
||
" <div id=\"piconnectolocalhost\">" +
|
||
" <input type=\"radio\" id=\"piconnectolocalhostcheckbox\" name=\"pilocalconnectiontype\" value=\"localhost\">" +
|
||
strings.messages.connectToLocalhost +
|
||
" </div>" +
|
||
" <div id=\"piconnectocurrenturl\">" +
|
||
" <input type=\"radio\" id=\"piconnectocurrenturlcheckbox\" name=\"pilocalconnectiontype\" value=\"currenturl\">" +
|
||
strings.messages.connectToWindowLocation +
|
||
" </div>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"inlineButtons\">" +
|
||
" <button id=\"piconnectok\" class=\"btn\"><i class=\"fa fa-wifi icon\"></i>" + strings.messages.connectToDevice + "</button>" +
|
||
" <button id=\"pirelease\" class=\"btn\"><i class=\"fa fa-times icon\"></i>" + strings.messages.disconnectFromDevice + "</button>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
"</div>";
|
||
|
||
window.displayHelper.showPopupDialog(connectionDialogHTML);
|
||
|
||
if (context.offLineMode) {
|
||
$('#pirelease').attr('disabled', true);
|
||
}
|
||
else {
|
||
$('#pirelease').attr('disabled', false);
|
||
}
|
||
|
||
$('#piconnectok').attr('disabled', true);
|
||
|
||
$('#piconnectionlabel').hide();
|
||
|
||
if (context.quickPiConnection.isConnected()) {
|
||
if (getSessionStorage('connectionMethod') == "USB") {
|
||
$('#piconwifi').removeClass('active');
|
||
$('#piconusb').addClass('active');
|
||
$('#pischoolcon').hide();
|
||
$('#piaddress').val("192.168.233.1");
|
||
|
||
$('#piconnectok').attr('disabled', true);
|
||
$('#piconnectionlabel').show();
|
||
$('#piconnectionlabel').text(strings.messages.canConnectoToUSB)
|
||
|
||
context.inUSBConnection = true;
|
||
context.inBTConnection = false;
|
||
} else if (getSessionStorage('connectionMethod') == "BT") {
|
||
$('#piconwifi').removeClass('active');
|
||
$('#piconbt').addClass('active');
|
||
$('#pischoolcon').hide();
|
||
|
||
$('#piaddress').val("192.168.233.2");
|
||
|
||
$('#piconnectok').attr('disabled', true);
|
||
$('#piconnectionlabel').show();
|
||
$('#piconnectionlabel').text(strings.messages.canConnectoToBT)
|
||
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = true;
|
||
} else if (getSessionStorage('connectionMethod') == "LOCAL") {
|
||
$('#piconlocal').trigger("click");
|
||
}
|
||
} else {
|
||
setSessionStorage('connectionMethod', "WIFI");
|
||
}
|
||
|
||
$('#piaddress').on('input', function (e) {
|
||
|
||
if (context.offLineMode)
|
||
{
|
||
var content = $('#piaddress').val();
|
||
|
||
if (content)
|
||
$('#piconnectok').attr('disabled', false);
|
||
else
|
||
$('#piconnectok').attr('disabled', true);
|
||
}
|
||
});
|
||
|
||
|
||
if (getSessionStorage('pilist')) {
|
||
populatePiList(JSON.parse(getSessionStorage('pilist')));
|
||
}
|
||
|
||
if (getSessionStorage('raspberryPiIpAddress')) {
|
||
$('#piaddress').val(getSessionStorage('raspberryPiIpAddress'));
|
||
$('#piaddress').trigger("input");
|
||
}
|
||
|
||
if (getSessionStorage('schoolkey')) {
|
||
$('#schoolkey').val(getSessionStorage('schoolkey'));
|
||
$('#pigetlist').attr("disabled", false);
|
||
}
|
||
|
||
function setLocalIp()
|
||
{
|
||
var localvalue = $('input[name=pilocalconnectiontype]:checked').val()
|
||
|
||
if (localvalue == "localhost") {
|
||
$('#piaddress').val(localhost);
|
||
$('#piaddress').trigger("input");
|
||
} else {
|
||
$('#piaddress').val(window.location.hostname);
|
||
$('#piaddress').trigger("input");
|
||
}
|
||
}
|
||
|
||
$('input[type=radio][name=pilocalconnectiontype]').change(function() {
|
||
setLocalIp();
|
||
});
|
||
|
||
function cleanUSBBTIP()
|
||
{
|
||
var ipaddress = $('#piaddress').val();
|
||
|
||
if (ipaddress == "192.168.233.1" ||
|
||
ipaddress == "192.168.233.2" ||
|
||
ipaddress == "localhost" ||
|
||
ipaddress == window.location.hostname)
|
||
{
|
||
$('#piaddress').val("");
|
||
$('#piaddress').trigger("input");
|
||
|
||
var schoolkey = $('#schoolkey').val();
|
||
if (schoolkey.length > 1)
|
||
$('#pigetlist').trigger("click");
|
||
}
|
||
}
|
||
|
||
cleanUSBBTIP();
|
||
|
||
$('#panel-body-local').hide();
|
||
|
||
if (context.localhostAvailable || context.windowLocationAvailable)
|
||
{
|
||
if (!context.quickPiConnection.isConnected() ||
|
||
getSessionStorage('connectionMethod') == "LOCAL")
|
||
{
|
||
$('#piconsel .btn').removeClass('active');
|
||
$('#piconlocal').addClass('active');
|
||
|
||
|
||
$('#pischoolcon').hide();
|
||
$('#piconnectionlabel').hide();
|
||
$('#panel-body-local').show();
|
||
setSessionStorage('connectionMethod', "LOCAL");
|
||
|
||
if (context.localhostAvailable &&
|
||
context.windowLocationAvailable)
|
||
{
|
||
$("#piconnectolocalhostcheckbox").prop("checked", true);
|
||
|
||
setLocalIp();
|
||
} else if (context.localhostAvailable) {
|
||
$('#piconnectolocalhost').hide();
|
||
$('#piconnectocurrenturlcheckbox').hide();
|
||
|
||
setLocalIp();
|
||
} else if (context.windowLocationAvailable) {
|
||
$('#piconnectocurrenturl').hide();
|
||
$('#piconnectolocalhostcheckbox').hide();
|
||
|
||
setLocalIp();
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
$('#panel-body-local').hide();
|
||
$("#piconlocal").hide();
|
||
}
|
||
|
||
|
||
$('#piconnectok').click(function () {
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = false;
|
||
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
if ($('#piusetunnel').is(":checked")) {
|
||
|
||
var piname = $("#pilist option:selected").text().split("-")[0].trim();
|
||
|
||
var url = "ws://api.quick-pi.org/client/" +
|
||
$('#schoolkey').val() + "-" +
|
||
piname +
|
||
"/api/v1/commands";
|
||
|
||
setSessionStorage('quickPiUrl', url);
|
||
context.quickPiConnection.connect(url);
|
||
|
||
} else {
|
||
var ipaddress = $('#piaddress').val();
|
||
setSessionStorage('raspberryPiIpAddress', ipaddress);
|
||
|
||
showasConnecting();
|
||
var url = "ws://" + ipaddress + ":5000/api/v1/commands";
|
||
setSessionStorage('quickPiUrl', url);
|
||
|
||
context.quickPiConnection.connect(url);
|
||
}
|
||
});
|
||
|
||
$('#pirelease').click(function () {
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = false;
|
||
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
// IF connected release lock
|
||
context.releasing = true;
|
||
context.quickPiConnection.releaseLock();
|
||
});
|
||
|
||
$('#picancel').click(function () {
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = false;
|
||
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
$('#schoolkey').on('input', function (e) {
|
||
var schoolkey = $('#schoolkey').val();
|
||
setSessionStorage('schoolkey', schoolkey);
|
||
|
||
if (schoolkey)
|
||
$('#pigetlist').attr("disabled", false);
|
||
else
|
||
$('#pigetlist').attr("disabled", true);
|
||
});
|
||
|
||
|
||
$('#pigetlist').click(function () {
|
||
var schoolkey = $('#schoolkey').val();
|
||
|
||
fetch('http://www.france-ioi.org/QuickPi/list.php?school=' + schoolkey)
|
||
.then(function (response) {
|
||
return response.json();
|
||
})
|
||
.then(function (jsonlist) {
|
||
populatePiList(jsonlist);
|
||
});
|
||
});
|
||
|
||
// Select device connexion methods
|
||
$('#piconsel .btn').click(function () {
|
||
if (!context.quickPiConnection.isConnected()) {
|
||
if (!$(this).hasClass('active')) {
|
||
$('#piconsel .btn').removeClass('active');
|
||
$(this).addClass('active');
|
||
}
|
||
}
|
||
});
|
||
|
||
$('#piconlocal').click(function () {
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = false;
|
||
|
||
cleanUSBBTIP();
|
||
|
||
if (!context.quickPiConnection.isConnected()) {
|
||
setLocalIp();
|
||
setSessionStorage('connectionMethod', "LOCAL");
|
||
$(this).addClass('active');
|
||
$('#panel-body-local').show();
|
||
$('#pischoolcon').hide();
|
||
$('#piconnectionlabel').hide();
|
||
|
||
$(this).addClass('active');
|
||
}
|
||
|
||
});
|
||
|
||
$('#piconwifi').click(function () {
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = false;
|
||
|
||
cleanUSBBTIP();
|
||
|
||
if (!context.quickPiConnection.isConnected()) {
|
||
setSessionStorage('connectionMethod', "WIFI");
|
||
$(this).addClass('active');
|
||
$('#panel-body-local').hide();
|
||
$('#pischoolcon').show();
|
||
$('#piconnectionlabel').hide();
|
||
}
|
||
|
||
});
|
||
|
||
$('#piconusb').click(function () {
|
||
if (!context.quickPiConnection.isConnected()) {
|
||
setSessionStorage('connectionMethod', "USB");
|
||
$('#piconnectok').attr('disabled', true);
|
||
$('#panel-body-local').hide();
|
||
$('#piconnectionlabel').show();
|
||
$('#piconnectionlabel').html(strings.messages.cantConnectoToUSB)
|
||
|
||
$(this).addClass('active');
|
||
$('#pischoolcon').hide();
|
||
$('#piaddress').val("192.168.233.1");
|
||
|
||
context.inUSBConnection = true;
|
||
context.inBTConnection = false;
|
||
|
||
function updateUSBAvailability(available) {
|
||
|
||
if (context.inUSBConnection && context.offLineMode) {
|
||
if (available) {
|
||
$('#piconnectok').attr('disabled', false);
|
||
|
||
$('#piconnectionlabel').text(strings.messages.canConnectoToUSB)
|
||
} else {
|
||
$('#piconnectok').attr('disabled', true);
|
||
|
||
$('#piconnectionlabel').html(strings.messages.cantConnectoToUSB)
|
||
}
|
||
|
||
setTimeout(function() {
|
||
context.quickPiConnection.isAvailable("192.168.233.1", updateUSBAvailability);
|
||
}, 1000);
|
||
}
|
||
}
|
||
|
||
updateUSBAvailability(false);
|
||
|
||
|
||
}
|
||
});
|
||
|
||
$('#piconbt').click(function () {
|
||
$('#piconnectionlabel').show();
|
||
if (!context.quickPiConnection.isConnected()) {
|
||
setSessionStorage('connectionMethod', "BT");
|
||
$('#piconnectok').attr('disabled', true);
|
||
$('#panel-body-local').hide();
|
||
$('#piconnectionlabel').show();
|
||
$('#piconnectionlabel').html(strings.messages.cantConnectoToBT)
|
||
|
||
$(this).addClass('active');
|
||
$('#pischoolcon').hide();
|
||
|
||
$('#piaddress').val("192.168.233.2");
|
||
|
||
context.inUSBConnection = false;
|
||
context.inBTConnection = true;
|
||
|
||
function updateBTAvailability(available) {
|
||
|
||
if (context.inBTConnection && context.offLineMode) {
|
||
if (available) {
|
||
$('#piconnectok').attr('disabled', false);
|
||
|
||
$('#piconnectionlabel').text(strings.messages.canConnectoToBT)
|
||
} else {
|
||
$('#piconnectok').attr('disabled', true);
|
||
|
||
$('#piconnectionlabel').html(strings.messages.cantConnectoToBT)
|
||
}
|
||
|
||
setTimeout(function() {
|
||
context.quickPiConnection.isAvailable("192.168.233.2", updateBTAvailability);
|
||
}, 1000);
|
||
}
|
||
}
|
||
|
||
updateBTAvailability(false);
|
||
}
|
||
});
|
||
|
||
function populatePiList(jsonlist) {
|
||
setSessionStorage('pilist', JSON.stringify(jsonlist));
|
||
|
||
var select = document.getElementById("pilist");
|
||
var first = true;
|
||
|
||
$('#pilist').empty();
|
||
$('#piusetunnel').attr('disabled', true);
|
||
|
||
for (var i = 0; i < jsonlist.length; i++) {
|
||
var pi = jsonlist[i];
|
||
|
||
var el = document.createElement("option");
|
||
|
||
var minutes = Math.round(jsonlist[i].seconds_since_ping / 60);
|
||
var timeago = "";
|
||
|
||
if (minutes < 60)
|
||
timeago = strings.messages.minutesago.format(minutes);
|
||
else
|
||
timeago = strings.messages.hoursago;
|
||
|
||
|
||
el.textContent = jsonlist[i].name + " - " + timeago;
|
||
el.value = jsonlist[i].ip;
|
||
|
||
select.appendChild(el);
|
||
|
||
if (first) {
|
||
$('#piaddress').val(jsonlist[i].ip);
|
||
$('#piaddress').trigger("input");
|
||
first = false;
|
||
$('#pilist').prop('disabled', false);
|
||
|
||
$('#piusetunnel').attr('disabled', false);
|
||
}
|
||
}
|
||
}
|
||
|
||
$('#pilist').on('change', function () {
|
||
$("#piaddress").val(this.value);
|
||
});
|
||
});
|
||
|
||
|
||
$('#pichangehat').click(function () {
|
||
window.displayHelper.showPopupDialog("<div class=\"content connectPi qpi\">" +
|
||
" <div class=\"panel-heading\">" +
|
||
" <h2 class=\"sectionTitle\">" +
|
||
" <span class=\"iconTag\"><i class=\"icon fas fa-list-ul\"></i></span>" +
|
||
strings.messages.chooseBoard +
|
||
" </h2>" +
|
||
" <div class=\"exit\" id=\"picancel\"><i class=\"icon fas fa-times\"></i></div>" +
|
||
" </div>" +
|
||
" <div class=\"panel-body\">" +
|
||
" <div id=boardlist>" +
|
||
" </div>" +
|
||
" <div panel-body-usbbt>" +
|
||
" <label id=\"piconnectionlabel\"></label>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
"</div>");
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
|
||
for (var i = 0; i < boardDefinitions.length; i++) {
|
||
let board = boardDefinitions[i];
|
||
var image = document.createElement('img');
|
||
image.src = getImg(board.image);
|
||
|
||
$('#boardlist').append(image).append(" ");
|
||
|
||
image.onclick = function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
context.changeBoard(board.name);
|
||
}
|
||
}
|
||
});
|
||
|
||
|
||
$('#pihatsetup').click(function () {
|
||
|
||
window.displayHelper.showPopupDialog("<div class=\"content connectPi qpi\">" +
|
||
" <div class=\"panel-heading\">" +
|
||
" <h2 class=\"sectionTitle\">" +
|
||
" <span class=\"iconTag\"><i class=\"icon fas fa-list-ul\"></i></span>" +
|
||
strings.messages.nameandports +
|
||
" </h2>" +
|
||
" <div class=\"exit\" id=\"picancel\"><i class=\"icon fas fa-times\"></i></div>" +
|
||
" </div>" +
|
||
" <div class=\"panel-body\">" +
|
||
" <table id='sensorTable' style=\"display:table-header-group;\">" +
|
||
" <tr>" +
|
||
" <th>" + strings.messages.name + "</th>" +
|
||
" <th>" + strings.messages.port + "</th>" +
|
||
" <th>" + strings.messages.state + "</th>" +
|
||
" </tr>" +
|
||
" </table>" +
|
||
" <!--" +
|
||
" <div>" +
|
||
" <input type=\"checkbox\" id=\"buzzeraudio\" value=\"buzzeron\"> Output audio trought audio buzzer<br>" +
|
||
" </div>" +
|
||
" <div class=\"inlineButtons\">" +
|
||
" <button id=\"pisetupok\" class=\"btn\"><i class=\"fas fa-cog icon\"></i>Set</button>" +
|
||
" </div>" +
|
||
" -->" +
|
||
" </div>" +
|
||
"</div>");
|
||
|
||
var table = document.getElementById("sensorTable");
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
function addNewRow()
|
||
{
|
||
var row = table.insertRow();
|
||
var type = row.insertCell();
|
||
var name = row.insertCell();
|
||
var port = row.insertCell();
|
||
|
||
return [type, name, port];
|
||
}
|
||
|
||
|
||
if (sensor.type == "stick")
|
||
{
|
||
var gpios = findSensorDefinition(sensor).gpios;
|
||
var cols = addNewRow();
|
||
|
||
cols[0].appendChild(document.createTextNode(sensor.type));
|
||
cols[1].appendChild(document.createTextNode(sensor.name + ".up"));
|
||
cols[2].appendChild(document.createTextNode("D" + gpios[0]));
|
||
|
||
var cols = addNewRow();
|
||
|
||
cols[0].appendChild(document.createTextNode(sensor.type));
|
||
cols[1].appendChild(document.createTextNode(sensor.name + ".down"));
|
||
cols[2].appendChild(document.createTextNode("D" + gpios[1]));
|
||
var cols = addNewRow();
|
||
|
||
cols[0].appendChild(document.createTextNode(sensor.type));
|
||
cols[1].appendChild(document.createTextNode(sensor.name + ".left"));
|
||
cols[2].appendChild(document.createTextNode("D" + gpios[2]));
|
||
var cols = addNewRow();
|
||
|
||
cols[0].appendChild(document.createTextNode(sensor.type));
|
||
cols[1].appendChild(document.createTextNode(sensor.name + ".right"));
|
||
cols[2].appendChild(document.createTextNode("D" + gpios[3]));
|
||
var cols = addNewRow();
|
||
|
||
cols[0].appendChild(document.createTextNode(sensor.type));
|
||
cols[1].appendChild(document.createTextNode(sensor.name + ".center"));
|
||
cols[2].appendChild(document.createTextNode("D" + gpios[4]));
|
||
|
||
/*
|
||
$('#stickupname').text(sensor.name + ".up");
|
||
|
||
$('#stickdownname').text(sensor.name + ".down");
|
||
$('#stickleftname').text(sensor.name + ".left");
|
||
$('#stickrightname').text(sensor.name + ".right");
|
||
$('#stickcentername').text(sensor.name + ".center");
|
||
|
||
$('#stickupport').text("D" + gpios[0]);
|
||
$('#stickdownport').text("D" + gpios[1]);
|
||
$('#stickleftport').text("D" + gpios[2]);
|
||
$('#stickrightport').text("D" + gpios[3]);
|
||
$('#stickcenterport').text("D" + gpios[4]);
|
||
|
||
$('#stickupstate').text(sensor.state[0] ? "ON" : "OFF");
|
||
$('#stickdownstate').text(sensor.state[1] ? "ON" : "OFF");
|
||
$('#stickleftstate').text(sensor.state[2] ? "ON" : "OFF");
|
||
$('#stickrightstate').text(sensor.state[3] ? "ON" : "OFF");
|
||
$('#stickcenterstate').text(sensor.state[4] ? "ON" : "OFF");
|
||
*/
|
||
}
|
||
else
|
||
{
|
||
var cols = addNewRow();
|
||
|
||
|
||
cols[0].appendChild(document.createTextNode(sensor.type));
|
||
cols[1].appendChild(document.createTextNode(sensor.name));
|
||
cols[2].appendChild(document.createTextNode(sensor.port));
|
||
}
|
||
|
||
}
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
});
|
||
|
||
$('#piinstall').click(function () {
|
||
context.blocklyHelper.reportValues = false;
|
||
|
||
var python_code = context.generatePythonSensorTable();
|
||
python_code += "\n\n";
|
||
python_code += window.task.displayedSubTask.blocklyHelper.getCode('python');
|
||
|
||
python_code = python_code.replace("from quickpi import *", "");
|
||
|
||
if (context.runner)
|
||
context.runner.stop();
|
||
|
||
context.installing = true;
|
||
$('#piinstallprogresss').show();
|
||
$('#piinstallcheck').hide();
|
||
|
||
context.quickPiConnection.installProgram(python_code, function () {
|
||
context.justinstalled = true;
|
||
$('#piinstallprogresss').hide();
|
||
$('#piinstallcheck').show();
|
||
});
|
||
});
|
||
|
||
|
||
if (parseInt(getSessionStorage('autoConnect'))) {
|
||
if (!context.quickPiConnection.isConnected() && !context.quickPiConnection.isConnecting()) {
|
||
$('#piconnect').attr("disabled", true);
|
||
context.quickPiConnection.connect(getSessionStorage('quickPiUrl'));
|
||
}
|
||
}
|
||
};
|
||
|
||
function addDefaultBoardSensors() {
|
||
var board = getCurrentBoard();
|
||
var boardDefaultSensors = board.default;
|
||
|
||
if (!boardDefaultSensors)
|
||
boardDefaultSensors = board.builtinSensors;
|
||
|
||
if (boardDefaultSensors)
|
||
{
|
||
for (var i = 0; i < boardDefaultSensors.length; i++) {
|
||
var sensor = boardDefaultSensors[i];
|
||
|
||
var newSensor = {
|
||
"type": sensor.type,
|
||
"port": sensor.port,
|
||
"builtin": true,
|
||
};
|
||
|
||
if (sensor.subType) {
|
||
newSensor.subType = sensor.subType;
|
||
}
|
||
|
||
newSensor.name = getSensorSuggestedName(sensor.type, sensor.suggestedName);
|
||
|
||
sensor.state = null;
|
||
sensor.callsInTimeSlot = 0;
|
||
sensor.lastTimeIncrease = 0;
|
||
|
||
infos.quickPiSensors.push(newSensor);
|
||
}
|
||
|
||
var newSensor = {
|
||
"type": "cloudstore",
|
||
"name": "cloud1",
|
||
};
|
||
infos.quickPiSensors.push(newSensor);
|
||
}
|
||
|
||
};
|
||
|
||
function getNewSensorSuggestedName(name) {
|
||
var maxvalue = 0;
|
||
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
var firstdigit = sensor.name.search(/\d/);
|
||
if (firstdigit > 0) {
|
||
var namepart = sensor.name.substring(0, firstdigit);
|
||
var numberpart = parseInt(sensor.name.substring(firstdigit), 10);
|
||
|
||
if (name == namepart && numberpart > maxvalue) {
|
||
maxvalue = numberpart;
|
||
}
|
||
}
|
||
}
|
||
|
||
return name + (maxvalue + 1);
|
||
}
|
||
|
||
function drawCustomSensorAdder(x, y, size) {
|
||
if (context.sensorAdder) {
|
||
context.sensorAdder.remove();
|
||
}
|
||
|
||
var centerx = x + size / 2;
|
||
var centery = y + size / 2;
|
||
var fontsize = size * .70;
|
||
|
||
context.sensorAdder = paper.text(centerx, centery, "+");
|
||
|
||
context.sensorAdder.attr({
|
||
"font-size": fontsize + "px",
|
||
fill: "lightgray"
|
||
});
|
||
context.sensorAdder.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
|
||
context.sensorAdder.click(function () {
|
||
|
||
window.displayHelper.showPopupDialog("<div class=\"content qpi\">" +
|
||
" <div class=\"panel-heading\">" +
|
||
" <h2 class=\"sectionTitle\">" +
|
||
" <span class=\"iconTag\"><i class=\"icon fas fa-list-ul\"></i></span>" +
|
||
strings.messages.addcomponent +
|
||
" </h2>" +
|
||
" <div class=\"exit\" id=\"picancel\"><i class=\"icon fas fa-times\"></i></div>" +
|
||
" </div>" +
|
||
" <div id=\"sensorPicker\" class=\"panel-body\">" +
|
||
" <label>" + strings.messages.selectcomponent + "</label>" +
|
||
" <div class=\"flex-container\">" +
|
||
" <div id=\"selector-image-container\" class=\"flex-col half\">" +
|
||
" <img id=\"selector-sensor-image\">" +
|
||
" </div>" +
|
||
" <div class=\"flex-col half\">" +
|
||
" <div class=\"form-group\">" +
|
||
" <div class=\"input-group\">" +
|
||
" <select id=\"selector-sensor-list\" class=\"custom-select\"></select>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"form-group\">" +
|
||
" <div class=\"input-group\">" +
|
||
" <select id=\"selector-sensor-port\" class=\"custom-select\"></select>" +
|
||
" </div>" +
|
||
" <label id=\"selector-label\"></label>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"singleButton\">" +
|
||
" <button id=\"selector-add-button\" class=\"btn btn-centered\"><i class=\"icon fa fa-check\"></i>" + strings.messages.add + "</button>" +
|
||
" </div>" +
|
||
"</div>");
|
||
|
||
var select = document.getElementById("selector-sensor-list");
|
||
for (var iSensorDef = 0; iSensorDef < sensorDefinitions.length; iSensorDef++) {
|
||
var sensorDefinition = sensorDefinitions[iSensorDef];
|
||
|
||
if (sensorDefinition.subTypes) {
|
||
for (var iSubType = 0; iSubType < sensorDefinition.subTypes.length; iSubType++) {
|
||
|
||
if (!sensorDefinition.pluggable && !sensorDefinition.subTypes[iSubType].pluggable)
|
||
continue;
|
||
|
||
|
||
var el = document.createElement("option");
|
||
el.textContent = sensorDefinition.description;
|
||
|
||
if (sensorDefinition.subTypes[iSubType].description)
|
||
el.textContent = sensorDefinition.subTypes[iSubType].description;
|
||
|
||
el.value = sensorDefinition.name;
|
||
el.value += "-" + sensorDefinition.subTypes[iSubType].subType;
|
||
select.appendChild(el);
|
||
}
|
||
} else {
|
||
if (!sensorDefinition.pluggable)
|
||
continue;
|
||
|
||
var el = document.createElement("option");
|
||
el.textContent = sensorDefinition.description;
|
||
el.value = sensorDefinition.name;
|
||
|
||
select.appendChild(el);
|
||
}
|
||
}
|
||
|
||
var board = getCurrentBoard();
|
||
if (board.builtinSensors) {
|
||
for (var i = 0; i < board.builtinSensors.length; i++) {
|
||
var sensor = board.builtinSensors[i];
|
||
var sensorDefinition = findSensorDefinition(sensor);
|
||
|
||
if (context.findSensor(sensor.type, sensor.port, false))
|
||
continue;
|
||
|
||
var el = document.createElement("option");
|
||
|
||
el.textContent = sensorDefinition.description + strings.messages.builtin;
|
||
el.value = sensorDefinition.name + "-";
|
||
|
||
if (sensor.subType)
|
||
el.value += sensor.subType;
|
||
|
||
el.value += "-" + sensor.port;
|
||
|
||
select.appendChild(el);
|
||
}
|
||
}
|
||
|
||
$('#selector-sensor-list').on('change', function () {
|
||
var values = this.value.split("-");
|
||
var builtinport = false;
|
||
|
||
var dummysensor = { type: values[0] };
|
||
|
||
if (values.length >= 2)
|
||
if (values[1])
|
||
dummysensor.subType = values[1];
|
||
|
||
if (values.length >= 3)
|
||
builtinport = values[2];
|
||
|
||
var sensorDefinition = findSensorDefinition(dummysensor);
|
||
|
||
var imageContainer = document.getElementById("selector-image-container");
|
||
while (imageContainer.firstChild) {
|
||
imageContainer.removeChild(imageContainer.firstChild);
|
||
}
|
||
for (var i = 0; i < sensorDefinition.selectorImages.length; i++) {
|
||
var image = document.createElement('img');
|
||
|
||
image.src = getImg(sensorDefinition.selectorImages[i]);
|
||
|
||
imageContainer.appendChild(image);
|
||
|
||
//$('#selector-sensor-image').attr("src", getImg(sensorDefinition.selectorImages[0]));
|
||
}
|
||
|
||
|
||
var portSelect = document.getElementById("selector-sensor-port");
|
||
$('#selector-sensor-port').empty();
|
||
var hasPorts = false;
|
||
if (builtinport) {
|
||
var option = document.createElement('option');
|
||
option.innerText = builtinport;
|
||
option.value = builtinport;
|
||
portSelect.appendChild(option);
|
||
hasPorts = true;
|
||
} else {
|
||
var ports = getCurrentBoard().portTypes[sensorDefinition.portType];
|
||
if (sensorDefinition.portType == "i2c")
|
||
{
|
||
ports = ["i2c"];
|
||
}
|
||
|
||
for (var iPort = 0; iPort < ports.length; iPort++) {
|
||
var port = sensorDefinition.portType + ports[iPort];
|
||
if (sensorDefinition.portType == "i2c")
|
||
port = "i2c";
|
||
|
||
if (!isPortUsed(sensorDefinition.name, port)) {
|
||
var option = document.createElement('option');
|
||
option.innerText = port;
|
||
option.value = port;
|
||
portSelect.appendChild(option);
|
||
hasPorts = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
if (!hasPorts) {
|
||
$('#selector-add-button').attr("disabled", true);
|
||
|
||
var object_function = strings.messages.actuator;
|
||
if (sensorDefinition.isSensor)
|
||
object_function = strings.messages.sensor;
|
||
|
||
$('#selector-label').text(strings.messages.noPortsAvailable.format(object_function, sensorDefinition.portType));
|
||
$('#selector-label').show();
|
||
}
|
||
else {
|
||
$('#selector-add-button').attr("disabled", false);
|
||
$('#selector-label').hide();
|
||
}
|
||
});
|
||
|
||
$('#selector-add-button').click(function () {
|
||
var sensorType = $("#selector-sensor-list option:selected").val();
|
||
var values = sensorType.split("-");
|
||
|
||
var dummysensor = { type: values[0] };
|
||
if (values.length == 2)
|
||
dummysensor.subType = values[1];
|
||
|
||
var sensorDefinition = findSensorDefinition(dummysensor);
|
||
|
||
|
||
var port = $("#selector-sensor-port option:selected").text();
|
||
var name = getNewSensorSuggestedName(sensorDefinition.suggestedName);
|
||
|
||
if(name == 'screen1') {
|
||
// prepend screen because squareSize func can't handle cells wrap
|
||
infos.quickPiSensors.unshift({
|
||
type: sensorDefinition.name,
|
||
subType: sensorDefinition.subType,
|
||
port: port,
|
||
name: name
|
||
});
|
||
|
||
} else {
|
||
infos.quickPiSensors.push({
|
||
type: sensorDefinition.name,
|
||
subType: sensorDefinition.subType,
|
||
port: port,
|
||
name: name
|
||
});
|
||
}
|
||
|
||
|
||
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
context.resetSensorTable();
|
||
context.resetDisplay();
|
||
});
|
||
|
||
|
||
$("#selector-sensor-list").trigger("change");
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
});
|
||
};
|
||
|
||
function isPortUsed(type, port) {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
if (port == "i2c")
|
||
{
|
||
if (sensor.type == type)
|
||
return true;
|
||
} else {
|
||
if (sensor.port == port)
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
};
|
||
|
||
// Straight from stack overflow :)
|
||
function squareSize(x, y, n, ratio) {
|
||
// Compute number of rows and columns, and cell size
|
||
var ratio = x / y * ratio;
|
||
var ncols_float = Math.sqrt(n * ratio);
|
||
var nrows_float = n / ncols_float;
|
||
|
||
// Find best option filling the whole height
|
||
var nrows1 = Math.ceil(nrows_float);
|
||
var ncols1 = Math.ceil(n / nrows1);
|
||
while (nrows1 * ratio < ncols1) {
|
||
nrows1++;
|
||
ncols1 = Math.ceil(n / nrows1);
|
||
}
|
||
var cell_size1 = y / nrows1;
|
||
|
||
// Find best option filling the whole width
|
||
var ncols2 = Math.ceil(ncols_float);
|
||
var nrows2 = Math.ceil(n / ncols2);
|
||
while (ncols2 < nrows2 * ratio) {
|
||
ncols2++;
|
||
nrows2 = Math.ceil(n / ncols2);
|
||
}
|
||
var cell_size2 = x / ncols2;
|
||
|
||
// Find the best values
|
||
var nrows, ncols, cell_size;
|
||
if (cell_size1 < cell_size2) {
|
||
nrows = nrows2;
|
||
ncols = ncols2;
|
||
cell_size = cell_size2;
|
||
} else {
|
||
nrows = nrows1;
|
||
ncols = ncols1;
|
||
cell_size = cell_size1;
|
||
}
|
||
|
||
return {
|
||
rows: ncols,
|
||
cols: nrows,
|
||
size: cell_size
|
||
};
|
||
}
|
||
|
||
function showasConnected() {
|
||
$('#piconnectprogress').hide();
|
||
$('#piinstallcheck').hide();
|
||
$('#piinstallprogresss').hide();
|
||
$('#piinstallui').show();
|
||
|
||
if (context.board == "quickpi")
|
||
$('#pihatsetup').show();
|
||
else
|
||
$('#pihatsetup').hide();
|
||
|
||
$('#piconnect').css('background-color', '#F9A423');
|
||
|
||
$('#piinstall').css('background-color', "#488FE1");
|
||
|
||
$('#piconnecttext').hide();
|
||
}
|
||
|
||
function showasConnecting() {
|
||
$('#piconnectprogress').show();
|
||
$('#piinstallcheck').hide();
|
||
$('#piinstallprogresss').hide();
|
||
}
|
||
|
||
function showasReleased() {
|
||
$('#piconnectprogress').hide();
|
||
$('#piinstallcheck').hide();
|
||
$('#piinstallprogresss').hide();
|
||
$('#piinstallui').hide();
|
||
$('#pihatsetup').hide();
|
||
$('#piconnect').css('background-color', '#F9A423');
|
||
$('#piconnecttext').show();
|
||
}
|
||
|
||
|
||
function showasDisconnected() {
|
||
$('#piconnectprogress').hide();
|
||
$('#piinstallcheck').hide();
|
||
$('#piinstallprogresss').hide();
|
||
$('#piinstall').css('background-color', 'gray');
|
||
$('#piconnect').css('background-color', 'gray');
|
||
$('#piconnecttext').hide();
|
||
}
|
||
|
||
function raspberryPiConnected() {
|
||
showasConnected();
|
||
|
||
context.resetSensorTable();
|
||
|
||
context.quickPiConnection.startNewSession();
|
||
|
||
context.liveUpdateCount = 0;
|
||
context.offLineMode = false;
|
||
|
||
setSessionStorage('autoConnect', "1");
|
||
|
||
context.recreateDisplay = true;
|
||
context.resetDisplay();
|
||
|
||
startSensorPollInterval();
|
||
}
|
||
|
||
function raspberryPiDisconnected(wasConnected, wrongversion) {
|
||
|
||
if (context.releasing || !wasConnected)
|
||
showasReleased();
|
||
else
|
||
showasDisconnected();
|
||
|
||
window.task.displayedSubTask.context.offLineMode = true;
|
||
|
||
if (context.quickPiConnection.wasLocked()) {
|
||
window.displayHelper.showPopupMessage(strings.messages.piPlocked, 'blanket');
|
||
} else if (wrongversion) {
|
||
window.displayHelper.showPopupMessage(strings.messages.wrongVersion, 'blanket');
|
||
} else if (!context.releasing && !wasConnected) {
|
||
window.displayHelper.showPopupMessage(strings.messages.cantConnect, 'blanket');
|
||
}
|
||
|
||
clearSensorPollInterval();
|
||
|
||
if (wasConnected && !context.releasing && !context.quickPiConnection.wasLocked() && !wrongversion) {
|
||
context.quickPiConnection.connect(getSessionStorage('quickPiUrl'));
|
||
} else {
|
||
// If I was never connected don't attempt to autoconnect again
|
||
setSessionStorage('autoConnect', "0");
|
||
window.task.displayedSubTask.context.resetDisplay();
|
||
}
|
||
|
||
}
|
||
|
||
function raspberryPiChangeBoard(board) {
|
||
|
||
if (board != "unknow")
|
||
{
|
||
window.task.displayedSubTask.context.changeBoard(board);
|
||
window.task.displayedSubTask.context.resetSensorTable();
|
||
}
|
||
}
|
||
|
||
|
||
// Update the context's display to the new scale (after a window resize for instance)
|
||
context.updateScale = function () {
|
||
if (!context.display) {
|
||
return;
|
||
}
|
||
|
||
var width = $('#virtualSensors').width();
|
||
var height = $('#virtualSensors').height();
|
||
|
||
if (!context.oldwidth ||
|
||
!context.oldheight ||
|
||
context.oldwidth != width ||
|
||
context.oldheight != height) {
|
||
|
||
context.oldwidth = width;
|
||
context.oldheight = height;
|
||
|
||
context.resetDisplay();
|
||
}
|
||
};
|
||
|
||
// When the context is unloaded, this function is called to clean up
|
||
// anything the context may have created
|
||
context.unload = function () {
|
||
// Do something here
|
||
clearSensorPollInterval();
|
||
if (context.display) {
|
||
// Do something here
|
||
}
|
||
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
sensor.removed = true;
|
||
}
|
||
|
||
};
|
||
|
||
function drawTimeLine() {
|
||
if (paper == undefined || !context.display)
|
||
return;
|
||
|
||
if (context.timelineText)
|
||
for (var i = 0; i < context.timelineText.length; i++) {
|
||
context.timelineText[i].remove();
|
||
}
|
||
|
||
context.timelineText = [];
|
||
|
||
var timelinewidth = context.maxTime * context.pixelsPerTime;
|
||
|
||
var pixelsPerTick = 50;
|
||
var numberofTicks = timelinewidth / pixelsPerTick;
|
||
var step = context.maxTime / numberofTicks;
|
||
|
||
if (step > 1000)
|
||
{
|
||
step = Math.round(step / 1000) * 1000;
|
||
}
|
||
else if (step > 500)
|
||
{
|
||
step = Math.round(step / 500) * 500;
|
||
}
|
||
else if (step > 100)
|
||
{
|
||
step = Math.round(step / 100) * 100;
|
||
}
|
||
else if (step > 10)
|
||
{
|
||
step = Math.round(step / 10) * 10;
|
||
}
|
||
|
||
var i = 0;
|
||
var lastx = 0;
|
||
var color = false;
|
||
|
||
var textStart = 0;
|
||
|
||
var timelabel = paper.text(textStart, context.timeLineY, strings.messages.timeLabel);
|
||
timelabel.attr({ "font-size": "10px", 'text-anchor': 'start', 'font-weight': 'bold', fill: "gray" });
|
||
context.timelineText.push(timelabel);
|
||
timelabel.node.style.MozUserSelect = "none";
|
||
timelabel.node.style.WebkitUserSelect = "none";
|
||
|
||
var bbox = timelabel.getBBox();
|
||
textStart = bbox.x + bbox.width + 3;
|
||
|
||
var timelabel = paper.text(textStart, context.timeLineY, '\uf00e');
|
||
timelabel.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
timelabel.node.style.fontWeight = "bold";
|
||
timelabel.node.style.MozUserSelect = "none";
|
||
timelabel.node.style.WebkitUserSelect = "none";
|
||
|
||
timelabel.attr({ "font-size": "20" + "px",
|
||
'text-anchor': 'start',
|
||
'font-weight': 'bold',
|
||
'fill': "#4A90E2",
|
||
});
|
||
context.timelineText.push(timelabel);
|
||
|
||
timelabel.click(function()
|
||
{
|
||
var originalzoom = context.quickPiZoom;
|
||
context.quickPiZoom += 0.3;
|
||
|
||
if (context.quickPiZoom < 1)
|
||
context.quickPiZoom = 1;
|
||
|
||
if (originalzoom != context.quickPiZoom)
|
||
context.resetDisplay();
|
||
});
|
||
|
||
|
||
var bbox = timelabel.getBBox();
|
||
textStart = bbox.x + bbox.width + 3;
|
||
|
||
var timelabel = paper.text(textStart, context.timeLineY, '\uf010');
|
||
timelabel.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
timelabel.node.style.fontWeight = "bold";
|
||
timelabel.node.style.MozUserSelect = "none";
|
||
timelabel.node.style.WebkitUserSelect = "none";
|
||
|
||
timelabel.attr({ "font-size": "20" + "px",
|
||
'text-anchor': 'start',
|
||
'font-weight': 'bold',
|
||
'fill': "#4A90E2",
|
||
});
|
||
context.timelineText.push(timelabel);
|
||
|
||
timelabel.click(function()
|
||
{
|
||
var originalzoom = context.quickPiZoom;
|
||
context.quickPiZoom -= 0.3;
|
||
|
||
if (context.quickPiZoom < 1)
|
||
context.quickPiZoom = 1;
|
||
|
||
if (originalzoom != context.quickPiZoom)
|
||
context.resetDisplay();
|
||
});
|
||
|
||
|
||
|
||
for (; i <= context.maxTime; i += step) {
|
||
var x = context.timelineStartx + (i * context.pixelsPerTime);
|
||
|
||
var labelText = (i / 1000).toFixed(2);
|
||
if (step >= 1000)
|
||
labelText = (i / 1000).toFixed(0);
|
||
|
||
|
||
var timelabel = paper.text(x, context.timeLineY, labelText);
|
||
|
||
timelabel.attr({ "font-size": "15px", 'text-anchor': 'center', 'font-weight': 'bold', fill: "gray" });
|
||
timelabel.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
|
||
context.timelineText.push(timelabel);
|
||
|
||
|
||
var timelinedivisor = paper.path(["M", x,
|
||
0,
|
||
"L", x,
|
||
context.timeLineY]);
|
||
timelinedivisor.attr({
|
||
"stroke-width": 1,
|
||
"stroke": "lightgray",
|
||
"opacity": 0.2,
|
||
'z-index': 100,
|
||
|
||
});
|
||
|
||
context.sensorStates.push(timelinedivisor);
|
||
}
|
||
if (!context.timeLineHoverLine || isElementRemoved(context.timeLineHoverLine)) {
|
||
context.timeLineHoverLine = paper.rect(0, 0, 0, 0);
|
||
}
|
||
|
||
context.timeLineHoverLine.attr({
|
||
"stroke": "blue",
|
||
"opacity": 0.2,
|
||
"opacity": 0
|
||
});
|
||
|
||
|
||
if (context.timeLineHoverPath) {
|
||
context.timeLineHoverPath.remove();
|
||
}
|
||
|
||
context.timeLineHoverPath = paper.rect(context.timelineStartx, 0, context.maxTime * context.pixelsPerTime, context.timeLineY);
|
||
|
||
context.timeLineHoverPath.attr({
|
||
"fill": "lightgray",
|
||
"stroke": "none",
|
||
"opacity": 0.0,
|
||
});
|
||
|
||
|
||
|
||
context.timeLineHoverPath.mousemove(function(event){
|
||
|
||
if (context.runner && context.runner.isRunning())
|
||
return;
|
||
|
||
$('#screentooltip').remove();
|
||
var scrolloffset = $('#virtualSensors').scrollLeft();
|
||
|
||
var ms = (event.clientX + scrolloffset - context.timelineStartx) / context.pixelsPerTime;
|
||
ms = Math.round(ms);
|
||
|
||
if (ms < -4)
|
||
return;
|
||
if (ms < 0)
|
||
ms = 0;
|
||
|
||
$( "body" ).append('<div id="screentooltip"></div>');
|
||
$('#screentooltip').css("position", "absolute");
|
||
$('#screentooltip').css("border", "1px solid gray");
|
||
$('#screentooltip').css("background-color", "#efefef");
|
||
$('#screentooltip').css("padding", "3px");
|
||
$('#screentooltip').css("z-index", "1000");
|
||
|
||
|
||
$('#screentooltip').css("left", event.clientX + 2).css("top", event.clientY + 2);
|
||
|
||
$('#screentooltip').text(ms.toString() + "ms");
|
||
|
||
|
||
for(var sensorName in context.gradingStatesBySensor) {
|
||
// Cycle through each sensor from the grading states
|
||
var sensor = findSensorByName(sensorName);
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
|
||
var expectedStates = context.gradingStatesBySensor[sensorName];
|
||
if(!expectedStates.length) { continue;}
|
||
|
||
var actualStates = context.actualStatesBySensor[sensorName];
|
||
var actualIdx = 0;
|
||
|
||
var currentSensorState = null;
|
||
|
||
// Check that we went through all expected states
|
||
for (var i = 0; i < context.gradingStatesBySensor[sensorName].length; i++) {
|
||
var expectedState = context.gradingStatesBySensor[sensorName][i];
|
||
|
||
if (expectedState.time >= ms)
|
||
{
|
||
break;
|
||
}
|
||
|
||
currentSensorState = expectedState;
|
||
}
|
||
|
||
if (currentSensorState)
|
||
{
|
||
sensor.state = currentSensorState.state;
|
||
drawSensor(sensor);
|
||
}
|
||
}
|
||
|
||
context.timeLineHoverLine.attr({
|
||
"x": event.clientX + scrolloffset,
|
||
"y": 0,
|
||
"width": 1,
|
||
"height": context.timeLineY,
|
||
|
||
"stroke-width": 4,
|
||
"stroke": "blue",
|
||
"opacity": 0.2,
|
||
"stroke-linecap": "square",
|
||
"stroke-linejoin": "round",
|
||
});
|
||
|
||
});
|
||
|
||
context.timeLineHoverPath.mouseout(function() {
|
||
if (context.runner && context.runner.isRunning())
|
||
return;
|
||
|
||
context.timeLineHoverLine.attr({
|
||
"opacity": 0.0,
|
||
});
|
||
|
||
$('#screentooltip').remove();
|
||
|
||
context.resetSensors();
|
||
for (var iSensor = 0; iSensor < infos.quickPiSensors.length; iSensor++) {
|
||
var sensor = infos.quickPiSensors[iSensor];
|
||
|
||
drawSensor(sensor);
|
||
}
|
||
|
||
});
|
||
|
||
|
||
if (!context.loopsForever) {
|
||
var endx = context.timelineStartx + (context.maxTime * context.pixelsPerTime);
|
||
var x = context.timelineStartx + (i * context.pixelsPerTime);
|
||
var timelabel = paper.text(x, context.timeLineY, '\uf11e');
|
||
timelabel.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
timelabel.node.style.fontWeight = "bold";
|
||
timelabel.node.style.MozUserSelect = "none";
|
||
timelabel.node.style.WebkitUserSelect = "none";
|
||
|
||
|
||
timelabel.attr({ "font-size": "20" + "px", 'text-anchor': 'middle', 'font-weight': 'bold', fill: "gray" });
|
||
context.timelineText.push(timelabel);
|
||
|
||
if (context.timeLineEndLine)
|
||
context.timeLineEndLine.remove();
|
||
|
||
context.timeLineEndLine = paper.path(["M", endx,
|
||
0,
|
||
"L", endx,
|
||
context.timeLineY]);
|
||
|
||
|
||
if (context.endFlagEnd)
|
||
context.endFlagEnd.remove();
|
||
context.endFlagEnd = paper.rect(endx, 0, x, context.timeLineY + 10);
|
||
context.endFlagEnd.attr({
|
||
"fill": "lightgray",
|
||
"stroke": "none",
|
||
"opacity": 0.2,
|
||
});
|
||
}
|
||
|
||
|
||
/*
|
||
paper.path(["M", context.timelineStartx,
|
||
paper.height - context.sensorSize * 3 / 4,
|
||
"L", paper.width,
|
||
paper.height - context.sensorSize * 3 / 4]);
|
||
*/
|
||
}
|
||
|
||
function drawCurrentTime() {
|
||
if (!paper || !context.display || isNaN(context.currentTime))
|
||
return;
|
||
/*
|
||
if (context.currentTimeText)
|
||
context.currentTimeText.remove();
|
||
|
||
context.currentTimeText = paper.text(0, paper.height - 40, context.currentTime.toString() + "ms");
|
||
context.currentTimeText.attr({
|
||
"font-size": "10px",
|
||
'text-anchor': 'start'
|
||
}); */
|
||
|
||
if (!context.autoGrading)
|
||
return;
|
||
|
||
var animationSpeed = 200; // ms
|
||
var startx = context.timelineStartx + (context.currentTime * context.pixelsPerTime);
|
||
|
||
var targetpath = ["M", startx, 0, "L", startx, context.timeLineY];
|
||
|
||
if (context.timeLineCurrent)
|
||
{
|
||
context.timeLineCurrent.animate({path: targetpath}, animationSpeed);
|
||
}
|
||
else
|
||
{
|
||
context.timeLineCurrent = paper.path(targetpath);
|
||
|
||
context.timeLineCurrent.attr({
|
||
"stroke-width": 5,
|
||
"stroke": "#678AB4",
|
||
"stroke-linecap": "round"
|
||
});
|
||
}
|
||
|
||
|
||
if (context.timeLineCircle)
|
||
{
|
||
context.timeLineCircle.animate({cx: startx}, animationSpeed);
|
||
}
|
||
else
|
||
{
|
||
var circleradius = 10;
|
||
context.timeLineCircle = paper.circle(startx, context.timeLineY, 10);
|
||
|
||
context.timeLineCircle.attr({
|
||
"fill": "white",
|
||
"stroke": "#678AB4"
|
||
});
|
||
}
|
||
|
||
var trianglew = 10;
|
||
var targetpath = ["M", startx, 0,
|
||
"L", startx + trianglew, 0,
|
||
"L", startx, trianglew,
|
||
"L", startx - trianglew, 0,
|
||
"L", startx, 0
|
||
];
|
||
|
||
if (context.timeLineTriangle)
|
||
{
|
||
context.timeLineTriangle.animate({path: targetpath}, animationSpeed);
|
||
}
|
||
else
|
||
{
|
||
context.timeLineTriangle = paper.path(targetpath);
|
||
|
||
context.timeLineTriangle.attr({
|
||
"fill": "#678AB4",
|
||
"stroke": "#678AB4"
|
||
});
|
||
}
|
||
|
||
}
|
||
|
||
function storeTimeLineState(sensor, state, startTime, endTime, type) {
|
||
var found = false;
|
||
var timelinestate = {
|
||
sensor: sensor,
|
||
state: state,
|
||
startTime: startTime,
|
||
endTime: endTime,
|
||
type: type
|
||
};
|
||
|
||
for (var i = 0; i < context.timeLineStates.length; i++) {
|
||
var currenttlstate = context.timeLineStates[i];
|
||
|
||
if (currenttlstate.sensor == sensor &&
|
||
currenttlstate.startTime == startTime &&
|
||
currenttlstate.endTime == endTime &&
|
||
currenttlstate.type == type) {
|
||
context.timeLineStates[i] = timelinestate;
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!found) {
|
||
context.timeLineStates.push(timelinestate);
|
||
}
|
||
}
|
||
|
||
|
||
function drawSensorTimeLineState(sensor, state, startTime, endTime, type, skipsave = false, expectedState = null) {
|
||
if (paper == undefined ||
|
||
!context.display ||
|
||
!context.autoGrading)
|
||
return;
|
||
|
||
if (!skipsave) {
|
||
storeTimeLineState(sensor, state, startTime, endTime, type);
|
||
}
|
||
|
||
var startx = context.timelineStartx + (startTime * context.pixelsPerTime);
|
||
var stateLenght = (endTime - startTime) * context.pixelsPerTime;
|
||
|
||
var ypositionmiddle = ((sensor.drawInfo.y + (context.timeLineSlotHeight * .5)));
|
||
|
||
var ypositiontop = sensor.drawInfo.y
|
||
var ypositionbottom = sensor.drawInfo.y + context.timeLineSlotHeight;
|
||
|
||
var color = "green";
|
||
var strokewidth = 4;
|
||
if (type == "expected" || type == "finnish") {
|
||
color = "lightgrey";
|
||
strokewidth = 8;
|
||
} else if (type == "wrong") {
|
||
color = "red";
|
||
strokewidth = 4;
|
||
}
|
||
else if (type == "actual") {
|
||
color = "yellow";
|
||
strokewidth = 4;
|
||
}
|
||
|
||
var isAnalog = findSensorDefinition(sensor).isAnalog;
|
||
var percentage = + state;
|
||
|
||
var drawnElements = [];
|
||
var deleteLastDrawnElements = true;
|
||
|
||
if (sensor.type == "accelerometer" ||
|
||
sensor.type == "gyroscope" ||
|
||
sensor.type == "magnetometer") {
|
||
|
||
if (state != null) {
|
||
for (var i = 0; i < 3; i++) {
|
||
var startx = context.timelineStartx + (startTime * context.pixelsPerTime);
|
||
var stateLenght = (endTime - startTime) * context.pixelsPerTime;
|
||
|
||
var yspace = context.timeLineSlotHeight / 3;
|
||
var ypositiontop = sensor.drawInfo.y + (yspace * i)
|
||
var ypositionbottom = ypositiontop + yspace;
|
||
|
||
var offset = (ypositionbottom - ypositiontop) * findSensorDefinition(sensor).getPercentageFromState(state[i], sensor);
|
||
|
||
if (type == "expected" || type == "finnish") {
|
||
color = "lightgrey";
|
||
strokewidth = 4;
|
||
} else if (type == "wrong") {
|
||
color = "red";
|
||
strokewidth = 2;
|
||
}
|
||
else if (type == "actual") {
|
||
color = "yellow";
|
||
strokewidth = 2;
|
||
}
|
||
|
||
if (sensor.lastAnalogState != null &&
|
||
sensor.lastAnalogState[i] != state[i]) {
|
||
|
||
var oldStatePercentage = findSensorDefinition(sensor).getPercentageFromState(sensor.lastAnalogState[i], sensor);
|
||
|
||
var previousOffset = (ypositionbottom - ypositiontop) * oldStatePercentage;
|
||
|
||
var joinline = paper.path(["M", startx,
|
||
ypositiontop + offset,
|
||
"L", startx,
|
||
ypositiontop + previousOffset]);
|
||
|
||
joinline.attr({
|
||
"stroke-width": strokewidth,
|
||
"stroke": color,
|
||
"stroke-linejoin": "round",
|
||
"stroke-linecap": "round"
|
||
});
|
||
context.sensorStates.push(joinline);
|
||
|
||
if (sensor.timelinelastxlabel == null)
|
||
sensor.timelinelastxlabel = [0, 0, 0];
|
||
|
||
if ((startx) - sensor.timelinelastxlabel[i] > 40)
|
||
{
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
var stateText = state.toString();
|
||
if(sensorDef && sensorDef.getStateString) {
|
||
stateText = sensorDef.getStateString(state[i]);
|
||
}
|
||
|
||
var paperText = paper.text(startx, ypositiontop + offset - 10, stateText);
|
||
drawnElements.push(paperText);
|
||
context.sensorStates.push(paperText);
|
||
|
||
sensor.timelinelastxlabel[i] = startx;
|
||
}
|
||
}
|
||
|
||
var stateline = paper.path(["M", startx,
|
||
ypositiontop + offset,
|
||
"L", startx + stateLenght,
|
||
ypositiontop + offset]);
|
||
|
||
stateline.attr({
|
||
"stroke-width": strokewidth,
|
||
"stroke": color,
|
||
"stroke-linejoin": "round",
|
||
"stroke-linecap": "round"
|
||
});
|
||
|
||
drawnElements.push(stateline);
|
||
context.sensorStates.push(stateline);
|
||
}
|
||
sensor.lastAnalogState = state == null ? [0, 0, 0] : state;
|
||
}
|
||
|
||
|
||
} else
|
||
if (isAnalog || sensor.showAsAnalog) {
|
||
var offset = (ypositionbottom - ypositiontop) * findSensorDefinition(sensor).getPercentageFromState(state, sensor);
|
||
|
||
if (type == "wrong") {
|
||
color = "red";
|
||
ypositionmiddle += 4;
|
||
}
|
||
else if (type == "actual") {
|
||
color = "yellow";
|
||
ypositionmiddle += 4;
|
||
}
|
||
|
||
if (sensor.lastAnalogState != null
|
||
&& sensor.lastAnalogState != state) {
|
||
var oldStatePercentage = findSensorDefinition(sensor).getPercentageFromState(sensor.lastAnalogState, sensor);
|
||
|
||
var previousOffset = (ypositionbottom - ypositiontop) * oldStatePercentage;
|
||
|
||
var joinline = paper.path(["M", startx,
|
||
ypositiontop + offset,
|
||
"L", startx,
|
||
ypositiontop + previousOffset]);
|
||
|
||
joinline.attr({
|
||
"stroke-width": strokewidth,
|
||
"stroke": color,
|
||
"stroke-linejoin": "round",
|
||
"stroke-linecap": "round"
|
||
});
|
||
|
||
context.sensorStates.push(joinline);
|
||
|
||
if (!sensor.timelinelastxlabel)
|
||
sensor.timelinelastxlabel = 0;
|
||
|
||
if (!sensor.timelinelastxlabel)
|
||
sensor.timelinelastxlabel = 0;
|
||
|
||
if ((startx) - sensor.timelinelastxlabel > 5)
|
||
{
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
var stateText = state.toString();
|
||
if(sensorDef && sensorDef.getStateString) {
|
||
stateText = sensorDef.getStateString(state);
|
||
}
|
||
|
||
var y = 0;
|
||
|
||
if (sensor.timelinestateup) {
|
||
y = ypositiontop + offset - 10;
|
||
sensor.timelinestateup = false;
|
||
}
|
||
else {
|
||
y = ypositiontop + offset + 10;
|
||
|
||
sensor.timelinestateup = true;
|
||
}
|
||
|
||
var paperText = paper.text(startx, y, stateText);
|
||
drawnElements.push(paperText);
|
||
context.sensorStates.push(paperText);
|
||
|
||
sensor.timelinelastxlabel = startx;
|
||
}
|
||
}
|
||
|
||
sensor.lastAnalogState = state == null ? 0 : state;
|
||
|
||
var stateline = paper.path(["M", startx,
|
||
ypositiontop + offset,
|
||
"L", startx + stateLenght,
|
||
ypositiontop + offset]);
|
||
|
||
stateline.attr({
|
||
"stroke-width": strokewidth,
|
||
"stroke": color,
|
||
"stroke-linejoin": "round",
|
||
"stroke-linecap": "round"
|
||
});
|
||
|
||
drawnElements.push(stateline);
|
||
context.sensorStates.push(stateline);
|
||
} else if (sensor.type == "stick") {
|
||
var stateToFA = [
|
||
"\uf062",
|
||
"\uf063",
|
||
"\uf060",
|
||
"\uf061",
|
||
"\uf111",
|
||
]
|
||
|
||
|
||
var spacing = context.timeLineSlotHeight / 5;
|
||
for (var i = 0; i < 5; i++)
|
||
{
|
||
if (state && state[i])
|
||
{
|
||
var ypos = sensor.drawInfo.y + (i * spacing);
|
||
var startingpath = ["M", startx,
|
||
ypos,
|
||
"L", startx,
|
||
ypos];
|
||
|
||
var targetpath = ["M", startx,
|
||
ypos,
|
||
"L", startx + stateLenght,
|
||
ypos];
|
||
|
||
if (type == "expected")
|
||
{
|
||
var stateline = paper.path(targetpath);
|
||
}
|
||
else
|
||
{
|
||
var stateline = paper.path(startingpath);
|
||
stateline.animate({path: targetpath}, 200);
|
||
}
|
||
|
||
stateline.attr({
|
||
"stroke-width": 2,
|
||
"stroke": color,
|
||
"stroke-linejoin": "round",
|
||
"stroke-linecap": "round"
|
||
});
|
||
|
||
drawnElements.push(stateline);
|
||
context.sensorStates.push(stateline);
|
||
|
||
if (type == "expected") {
|
||
sensor.stateArrow = paper.text(startx, ypos + 7, stateToFA[i]);
|
||
context.sensorStates.push(sensor.stateArrow);
|
||
|
||
sensor.stateArrow.attr({
|
||
"text-anchor": "start",
|
||
"font": "Font Awesome 5 Free",
|
||
"stroke": color,
|
||
"fill": color,
|
||
"font-size": (strokewidth * 2) + "px"
|
||
});
|
||
|
||
sensor.stateArrow.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
sensor.stateArrow.node.style.fontWeight = "bold";
|
||
}
|
||
}
|
||
}
|
||
|
||
} else if (sensor.type == "screen" && state) {
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
if (type != "actual" || !sensor.lastScreenState || !sensorDef.compareState(sensor.lastScreenState, state))
|
||
{
|
||
sensor.lastScreenState = state;
|
||
if (state.isDrawingData) {
|
||
var stateBubble = paper.text(startx, ypositiontop + 10, '\uf303');
|
||
|
||
stateBubble.attr({
|
||
"font": "Font Awesome 5 Free",
|
||
"stroke": color,
|
||
"fill": color,
|
||
"font-size": (4 * 2) + "px"
|
||
});
|
||
|
||
stateBubble.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
stateBubble.node.style.fontWeight = "bold";
|
||
|
||
$(stateBubble.node).css("z-index", "1");
|
||
|
||
function showPopup(event) {
|
||
|
||
if (!sensor.showingTooltip)
|
||
{
|
||
$( "body" ).append('<div id="screentooltip"></div>');
|
||
|
||
$('#screentooltip').css("position", "absolute");
|
||
$('#screentooltip').css("border", "1px solid gray");
|
||
$('#screentooltip').css("background-color", "#efefef");
|
||
$('#screentooltip').css("padding", "3px");
|
||
$('#screentooltip').css("z-index", "1000");
|
||
$('#screentooltip').css("width", "262px");
|
||
$('#screentooltip').css("height", "70px");
|
||
|
||
$('#screentooltip').css("left", event.clientX+2).css("top", event.clientY+2);
|
||
|
||
var canvas = document.createElement("canvas");
|
||
canvas.id = "tooltipcanvas";
|
||
canvas.width = 128 * 2;
|
||
canvas.height = 32 * 2;
|
||
$('#screentooltip').append(canvas);
|
||
|
||
|
||
$(canvas).css("position", "absolute");
|
||
$(canvas).css("z-index", "1500");
|
||
$(canvas).css("left", 3).css("top", 3);
|
||
|
||
|
||
var ctx = canvas.getContext('2d');
|
||
|
||
if (expectedState && type == "wrong") {
|
||
screenDrawing.renderDifferences(expectedState, state, canvas, 2);
|
||
} else {
|
||
screenDrawing.renderToCanvas(state, canvas, 2);
|
||
}
|
||
|
||
sensor.showingTooltip = true;
|
||
}
|
||
};
|
||
|
||
$(stateBubble.node).mouseenter(showPopup);
|
||
$(stateBubble.node).click(showPopup);
|
||
|
||
$(stateBubble.node).mouseleave(function(event) {
|
||
sensor.showingTooltip = false;
|
||
$('#screentooltip').remove();
|
||
});
|
||
|
||
} else {
|
||
var stateBubble = paper.text(startx, ypositionmiddle + 10, '\uf27a');
|
||
|
||
stateBubble.attr({
|
||
"font": "Font Awesome 5 Free",
|
||
"stroke": color,
|
||
"fill": color,
|
||
"font-size": (strokewidth * 2) + "px"
|
||
});
|
||
|
||
stateBubble.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
stateBubble.node.style.fontWeight = "bold";
|
||
|
||
function showPopup() {
|
||
if (!sensor.tooltip) {
|
||
sensor.tooltipText = paper.text(startx, ypositionmiddle + 50, state.line1 + "\n" + (state.line2 ? state.line2 : ""));
|
||
|
||
var textDimensions = sensor.tooltipText.getBBox();
|
||
|
||
sensor.tooltip = paper.rect(textDimensions.x - 15, textDimensions.y - 15, textDimensions.width + 30, textDimensions.height + 30);
|
||
sensor.tooltip.attr({
|
||
"stroke": "black",
|
||
"stroke-width": 2,
|
||
"fill": "white",
|
||
});
|
||
|
||
sensor.tooltipText.toFront();
|
||
}
|
||
};
|
||
|
||
stateBubble.click(showPopup);
|
||
|
||
stateBubble.hover(showPopup, function () {
|
||
if (sensor.tooltip) {
|
||
sensor.tooltip.remove();
|
||
sensor.tooltip = null;
|
||
}
|
||
if (sensor.tooltipText) {
|
||
sensor.tooltipText.remove();
|
||
sensor.tooltipText = null;
|
||
}
|
||
});
|
||
}
|
||
drawnElements.push(stateBubble);
|
||
context.sensorStates.push(stateBubble);
|
||
} else {
|
||
deleteLastDrawnElements = false;
|
||
}
|
||
} else if (sensor.type == "cloudstore") {
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
if (type != "actual" || !sensor.lastScreenState || !sensorDef.compareState(sensor.lastScreenState, state))
|
||
{
|
||
sensor.lastScreenState = state;
|
||
var stateBubble = paper.text(startx, ypositionmiddle + 10, '\uf044');
|
||
|
||
stateBubble.attr({
|
||
"font": "Font Awesome 5 Free",
|
||
"stroke": color,
|
||
"fill": color,
|
||
"font-size": (4 * 2) + "px"
|
||
});
|
||
|
||
stateBubble.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
stateBubble.node.style.fontWeight = "bold";
|
||
|
||
function showPopup(event) {
|
||
|
||
if (!sensor.showingTooltip)
|
||
{
|
||
$( "body" ).append('<div id="screentooltip"></div>');
|
||
|
||
$('#screentooltip').css("position", "absolute");
|
||
$('#screentooltip').css("border", "1px solid gray");
|
||
$('#screentooltip').css("background-color", "#efefef");
|
||
$('#screentooltip').css("padding", "3px");
|
||
$('#screentooltip').css("z-index", "1000");
|
||
/*
|
||
$('#screentooltip').css("width", "262px");
|
||
$('#screentooltip').css("height", "70px");*/
|
||
|
||
$('#screentooltip').css("left", event.clientX+2).css("top", event.clientY+2);
|
||
|
||
|
||
if (expectedState && type == "wrong") {
|
||
var div = quickPiStore.renderDifferences(expectedState, state);
|
||
$('#screentooltip').append(div);
|
||
} else {
|
||
for (var property in state) {
|
||
var div = document.createElement("div");
|
||
$(div).text(property + " = " + state[property]);
|
||
$('#screentooltip').append(div);
|
||
}
|
||
}
|
||
|
||
sensor.showingTooltip = true;
|
||
}
|
||
};
|
||
|
||
$(stateBubble.node).mouseenter(showPopup);
|
||
$(stateBubble.node).click(showPopup);
|
||
|
||
$(stateBubble.node).mouseleave(function(event) {
|
||
sensor.showingTooltip = false;
|
||
$('#screentooltip').remove();
|
||
});
|
||
|
||
drawnElements.push(stateBubble);
|
||
context.sensorStates.push(stateBubble);
|
||
|
||
} else {
|
||
deleteLastDrawnElements = false;
|
||
}
|
||
} else if (percentage != 0) {
|
||
if (type == "wrong" || type == "actual") {
|
||
ypositionmiddle += 2;
|
||
}
|
||
|
||
if (type == "expected") {
|
||
var c = paper.rect(startx, ypositionmiddle, stateLenght, strokewidth);
|
||
c.attr({
|
||
"stroke": "none",
|
||
"fill": color,
|
||
});
|
||
|
||
} else {
|
||
var c = paper.rect(startx, ypositionmiddle, 0, strokewidth);
|
||
c.attr({
|
||
"stroke": "none",
|
||
"fill": color,
|
||
});
|
||
|
||
c.animate({ width: stateLenght }, 200);
|
||
}
|
||
drawnElements.push(c);
|
||
context.sensorStates.push(c);
|
||
}
|
||
|
||
if (type == "wrong") {
|
||
/*
|
||
wrongindicator = paper.path(["M", startx,
|
||
sensor.drawInfo.y,
|
||
"L", startx + stateLenght,
|
||
sensor.drawInfo.y + sensor.drawInfo.height,
|
||
|
||
"M", startx,
|
||
sensor.drawInfo.y + sensor.drawInfo.height,
|
||
"L", startx + stateLenght,
|
||
sensor.drawInfo.y
|
||
]);
|
||
|
||
wrongindicator.attr({
|
||
"stroke-width": 5, "stroke" : "red", "stroke-linecap": "round" });*/
|
||
}
|
||
|
||
if(type == 'actual' || type == 'wrong') {
|
||
if(!sensor.drawnGradingElements) {
|
||
sensor.drawnGradingElements = [];
|
||
} else if(deleteLastDrawnElements) {
|
||
for(var i = 0; i < sensor.drawnGradingElements.length; i++) {
|
||
var dge = sensor.drawnGradingElements[i];
|
||
if(dge.time >= startTime) {
|
||
for(var j = 0; j < dge.elements.length; j++) {
|
||
dge.elements[j].remove();
|
||
}
|
||
sensor.drawnGradingElements.splice(i, 1);
|
||
i -= 1;
|
||
}
|
||
}
|
||
}
|
||
if(drawnElements.length) {
|
||
sensor.drawnGradingElements.push({time: startTime, elements: drawnElements});
|
||
}
|
||
}
|
||
|
||
// Make sure the current time bar is always on top of states
|
||
drawCurrentTime();
|
||
}
|
||
|
||
function getImg(filename) {
|
||
// Get the path to an image stored in bebras-modules
|
||
return (window.modulesPath ? window.modulesPath : '../../modules/') + 'img/quickpi/' + filename;
|
||
}
|
||
|
||
function createSlider(sensor, max, min, x, y, w, h, index)
|
||
{
|
||
var sliderobj = {};
|
||
sliderobj.sliderdata = {};
|
||
|
||
sliderobj.index = index;
|
||
sliderobj.min = min;
|
||
sliderobj.max = max;
|
||
|
||
var outsiderectx = x;
|
||
var outsiderecty = y;
|
||
var outsidewidth = w / 6;
|
||
var outsideheight = h;
|
||
|
||
var insidewidth = outsidewidth / 6;
|
||
sliderobj.sliderdata.insideheight = h * 0.60;
|
||
|
||
var insiderectx = outsiderectx + (outsidewidth / 2) - (insidewidth / 2);
|
||
sliderobj.sliderdata.insiderecty = outsiderecty + (outsideheight / 2) - (sliderobj.sliderdata.insideheight / 2);
|
||
|
||
var circleradius = (outsidewidth / 2) - 1;
|
||
|
||
var pluscirclex = outsiderectx + (outsidewidth / 2);
|
||
var pluscircley = outsiderecty + circleradius + 1;
|
||
|
||
var minuscirclex = pluscirclex;
|
||
var minuscircley = outsiderecty + outsideheight - circleradius - 1;
|
||
|
||
paper.setStart();
|
||
|
||
sliderobj.sliderrect = paper.rect(outsiderectx, outsiderecty, outsidewidth, outsideheight, outsidewidth / 2);
|
||
sliderobj.sliderrect.attr("fill", "#468DDF");
|
||
sliderobj.sliderrect.attr("stroke", "#468DDF");
|
||
|
||
sliderobj.sliderrect = paper.rect(insiderectx, sliderobj.sliderdata.insiderecty, insidewidth, sliderobj.sliderdata.insideheight, 2);
|
||
sliderobj.sliderrect.attr("fill", "#2E5D94");
|
||
sliderobj.sliderrect.attr("stroke", "#2E5D94");
|
||
|
||
|
||
sliderobj.plusset = paper.set();
|
||
|
||
sliderobj.pluscircle = paper.circle(pluscirclex, pluscircley, circleradius);
|
||
sliderobj.pluscircle.attr("fill", "#F5A621");
|
||
sliderobj.pluscircle.attr("stroke", "#F5A621");
|
||
|
||
sliderobj.plus = paper.text(pluscirclex, pluscircley, "+");
|
||
sliderobj.plus.attr({ fill: "white" });
|
||
sliderobj.plus.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
|
||
sliderobj.plusset.push(sliderobj.pluscircle, sliderobj.plus);
|
||
|
||
sliderobj.plusset.click(function () {
|
||
var step = 1;
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
if (sensorDef.step)
|
||
step = sensorDef.step;
|
||
|
||
if (Array.isArray(sensor.state)) {
|
||
if (sensor.state[sliderobj.index] < sliderobj.max)
|
||
sensor.state[sliderobj.index] += step;
|
||
}
|
||
else
|
||
{
|
||
if (sensor.state < sliderobj.max)
|
||
sensor.state += step;
|
||
}
|
||
|
||
drawSensor(sensor, true);
|
||
});
|
||
|
||
|
||
sliderobj.minusset = paper.set();
|
||
|
||
sliderobj.minuscircle = paper.circle(minuscirclex, minuscircley, circleradius);
|
||
sliderobj.minuscircle.attr("fill", "#F5A621");
|
||
sliderobj.minuscircle.attr("stroke", "#F5A621");
|
||
|
||
sliderobj.minus = paper.text(minuscirclex, minuscircley, "-");
|
||
sliderobj.minus.attr({ fill: "white" });
|
||
sliderobj.minus.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
|
||
sliderobj.minusset.push(sliderobj.minuscircle, sliderobj.minus);
|
||
|
||
sliderobj.minusset.click(function () {
|
||
|
||
var step = 1;
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
if (sensorDef.step)
|
||
step = sensorDef.step;
|
||
|
||
if (Array.isArray(sensor.state)) {
|
||
if (sensor.state[sliderobj.index] > sliderobj.min)
|
||
sensor.state[sliderobj.index] -= step;
|
||
} else {
|
||
if (sensor.state > sliderobj.min)
|
||
sensor.state -= step;
|
||
}
|
||
|
||
drawSensor(sensor, true);
|
||
});
|
||
|
||
|
||
var thumbwidth = outsidewidth * .80;
|
||
sliderobj.sliderdata.thumbheight = outsidewidth * 1.4;
|
||
sliderobj.sliderdata.scale = (sliderobj.sliderdata.insideheight - sliderobj.sliderdata.thumbheight);
|
||
|
||
|
||
if (Array.isArray(sensor.state)) {
|
||
var percentage = findSensorDefinition(sensor).getPercentageFromState(sensor.state[index], sensor);
|
||
} else {
|
||
var percentage = findSensorDefinition(sensor).getPercentageFromState(sensor.state, sensor);
|
||
}
|
||
|
||
|
||
var thumby = sliderobj.sliderdata.insiderecty + sliderobj.sliderdata.insideheight - sliderobj.sliderdata.thumbheight - (percentage * sliderobj.sliderdata.scale);
|
||
|
||
var thumbx = insiderectx + (insidewidth / 2) - (thumbwidth / 2);
|
||
|
||
sliderobj.thumb = paper.rect(thumbx, thumby, thumbwidth, sliderobj.sliderdata.thumbheight, outsidewidth / 2);
|
||
sliderobj.thumb.attr("fill", "#F5A621");
|
||
sliderobj.thumb.attr("stroke", "#F5A621");
|
||
|
||
sliderobj.slider = paper.setFinish();
|
||
|
||
sliderobj.thumb.drag(
|
||
function (dx, dy, x, y, event) {
|
||
|
||
var newy = sliderobj.sliderdata.zero + dy;
|
||
|
||
if (newy < sliderobj.sliderdata.insiderecty)
|
||
newy = sliderobj.sliderdata.insiderecty;
|
||
|
||
if (newy > sliderobj.sliderdata.insiderecty + sliderobj.sliderdata.insideheight - sliderobj.sliderdata.thumbheight)
|
||
newy = sliderobj.sliderdata.insiderecty + sliderobj.sliderdata.insideheight - sliderobj.sliderdata.thumbheight;
|
||
|
||
sliderobj.thumb.attr('y', newy);
|
||
|
||
var percentage = 1 - ((newy - sliderobj.sliderdata.insiderecty) / sliderobj.sliderdata.scale);
|
||
|
||
if (Array.isArray(sensor.state)) {
|
||
sensor.state[sliderobj.index] = findSensorDefinition(sensor).getStateFromPercentage(percentage);
|
||
} else {
|
||
sensor.state = findSensorDefinition(sensor).getStateFromPercentage(percentage);
|
||
}
|
||
drawSensor(sensor, true);
|
||
},
|
||
function (x, y, event) {
|
||
sliderobj.sliderdata.zero = sliderobj.thumb.attr('y');
|
||
|
||
},
|
||
function (event) {
|
||
}
|
||
);
|
||
|
||
return sliderobj;
|
||
}
|
||
|
||
|
||
function setSlider(sensor, juststate, imgx, imgy, imgw, imgh, min, max, triaxial) {
|
||
if (juststate) {
|
||
|
||
if (Array.isArray(sensor.state)) {
|
||
for (var i = 0; i < sensor.state.length; i++) {
|
||
if (sensor.sliders[i] == undefined)
|
||
continue;
|
||
|
||
var percentage = findSensorDefinition(sensor).getPercentageFromState(sensor.state[i], sensor);
|
||
|
||
thumby = sensor.sliders[i].sliderdata.insiderecty +
|
||
sensor.sliders[i].sliderdata.insideheight -
|
||
sensor.sliders[i].sliderdata.thumbheight -
|
||
(percentage * sensor.sliders[i].sliderdata.scale);
|
||
|
||
sensor.sliders[i].thumb.attr('y', thumby);
|
||
}
|
||
} else {
|
||
var percentage = findSensorDefinition(sensor).getPercentageFromState(sensor.state, sensor);
|
||
|
||
thumby = sensor.sliders[0].sliderdata.insiderecty +
|
||
sensor.sliders[0].sliderdata.insideheight -
|
||
sensor.sliders[0].sliderdata.thumbheight -
|
||
(percentage * sensor.sliders[0].sliderdata.scale);
|
||
|
||
sensor.sliders[0].thumb.attr('y', thumby);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
removeSlider(sensor);
|
||
|
||
|
||
sensor.sliders = [];
|
||
|
||
var actuallydragged;
|
||
|
||
sensor.hasslider = true;
|
||
sensor.focusrect.drag(
|
||
function (dx, dy, x, y, event) {
|
||
if (sensor.sliders.length != 1)
|
||
return;
|
||
|
||
var newy = sensor.sliders[0].sliderdata.zero + dy;
|
||
|
||
if (newy < sensor.sliders[0].sliderdata.insiderecty)
|
||
newy = sensor.sliders[0].sliderdata.insiderecty;
|
||
|
||
if (newy > sensor.sliders[0].sliderdata.insiderecty + sensor.sliders[0].sliderdata.insideheight - sensor.sliders[0].sliderdata.thumbheight)
|
||
newy = sensor.sliders[0].sliderdata.insiderecty + sensor.sliders[0].sliderdata.insideheight - sensor.sliders[0].sliderdata.thumbheight;
|
||
|
||
sensor.sliders[0].thumb.attr('y', newy);
|
||
|
||
var percentage = 1 - ((newy - sensor.sliders[0].sliderdata.insiderecty) / sensor.sliders[0].sliderdata.scale);
|
||
|
||
sensor.state = findSensorDefinition(sensor).getStateFromPercentage(percentage);
|
||
drawSensor(sensor, true);
|
||
|
||
actuallydragged++;
|
||
},
|
||
function (x, y, event) {
|
||
showSlider();
|
||
actuallydragged = 0;
|
||
|
||
if (sensor.sliders.length == 1)
|
||
sensor.sliders[0].sliderdata.zero = sensor.sliders[0].thumb.attr('y');
|
||
},
|
||
function (event) {
|
||
if (actuallydragged > 4) {
|
||
hideSlider(sensor);
|
||
}
|
||
}
|
||
);
|
||
|
||
function showSlider() {
|
||
hideSlider(sensorWithSlider);
|
||
sensorWithSlider = sensor;
|
||
|
||
if (Array.isArray(sensor.state)) {
|
||
|
||
var offset = 0;
|
||
var sign = -1;
|
||
if (sensor.drawInfo.x -
|
||
((sensor.state.length - 1) * sensor.drawInfo.width / 5) < 0)
|
||
{
|
||
sign = 1;
|
||
offset = sensor.drawInfo.width * .70;
|
||
}
|
||
|
||
// if offset is equal to 0, we need to reverse
|
||
if (offset == 0) {
|
||
for (var i = 0; i < sensor.state.length; i++) {
|
||
var sliderobj = createSlider(sensor,
|
||
max,
|
||
min,
|
||
sensor.drawInfo.x + offset + (sign * Math.abs(i + 1 - sensor.state.length) * sensor.drawInfo.height / 5),
|
||
sensor.drawInfo.y,
|
||
sensor.drawInfo.height,
|
||
sensor.drawInfo.height,
|
||
i);
|
||
|
||
sensor.sliders.push(sliderobj);
|
||
}
|
||
}
|
||
else {
|
||
for (var i = 0; i < sensor.state.length; i++) {
|
||
var sliderobj = createSlider(sensor,
|
||
max,
|
||
min,
|
||
sensor.drawInfo.x + offset + (sign * i * sensor.drawInfo.height / 5),
|
||
sensor.drawInfo.y,
|
||
sensor.drawInfo.height,
|
||
sensor.drawInfo.height,
|
||
i);
|
||
|
||
sensor.sliders.push(sliderobj);
|
||
}
|
||
}
|
||
} else {
|
||
var sliderobj = createSlider(sensor,
|
||
max,
|
||
min,
|
||
sensor.drawInfo.x,
|
||
sensor.drawInfo.y,
|
||
sensor.drawInfo.height,
|
||
sensor.drawInfo.height,
|
||
0);
|
||
sensor.sliders.push(sliderobj);
|
||
}
|
||
}
|
||
}
|
||
|
||
function removeSlider(sensor) {
|
||
if (sensor.hasslider && sensor.focusrect) {
|
||
sensor.focusrect.undrag();
|
||
sensor.hasslider = false;
|
||
}
|
||
|
||
if (sensor.sliders) {
|
||
|
||
for (var i = 0; i < sensor.sliders.length; i++) {
|
||
sensor.sliders[i].slider.remove();
|
||
}
|
||
|
||
sensor.sliders = [];
|
||
}
|
||
}
|
||
|
||
function sensorInConnectedModeError() {
|
||
window.displayHelper.showPopupMessage(strings.messages.sensorInOnlineMode, 'blanket');
|
||
}
|
||
|
||
function actuatorsInRunningModeError() {
|
||
window.displayHelper.showPopupMessage(strings.messages.actuatorsWhenRunning, 'blanket');
|
||
}
|
||
|
||
function isElementRemoved(element) {
|
||
return !element.paper.canvas || !element.node.parentElement;
|
||
}
|
||
|
||
var irRemoteDialog = "<div class=\"content qpi\">" +
|
||
" <div class=\"panel-heading\">" +
|
||
" <h2 class=\"sectionTitle\">" +
|
||
" <span class=\"iconTag\"><i class=\"icon fas fa-list-ul\"></i></span>" +
|
||
strings.messages.irRemoteControl +
|
||
" </h2>" +
|
||
" <div class=\"exit\" id=\"picancel\"><i class=\"icon fas fa-times\"></i></div>" +
|
||
" </div>" +
|
||
" <div id=\"sensorPicker\" class=\"panel-body\">" +
|
||
" <div id=\"piremotemessage\" >" +
|
||
" </div>" +
|
||
" <div id=\"piremotecontent\" >" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"singleButton\">" +
|
||
" <button id=\"picancel2\" class=\"btn btn-centered\"><i class=\"icon fa fa-check\"></i>" + strings.messages.closeDialog + "</button>" +
|
||
" </div>" +
|
||
"</div>";
|
||
|
||
function drawSensor(sensor, juststate = false, donotmovefocusrect = false) {
|
||
if (paper == undefined || !context.display || !sensor.drawInfo)
|
||
return;
|
||
|
||
var scrolloffset = 0;
|
||
var fadeopacity = 1;
|
||
|
||
var imgw = sensor.drawInfo.width / 1.8;
|
||
var imgh = sensor.drawInfo.height / 2;
|
||
imgw = imgh;
|
||
|
||
var imgx = sensor.drawInfo.x - (imgw / 2) + (sensor.drawInfo.width / 2);
|
||
var imgy = sensor.drawInfo.y + (sensor.drawInfo.height / 2) - (imgh / 2);
|
||
|
||
var state1x = (imgx + imgw) + 3;
|
||
var state1y = imgy + imgh / 3;
|
||
|
||
var state1x = sensor.drawInfo.x + (sensor.drawInfo.width / 2)
|
||
var state1y = imgy + imgh + 6;
|
||
var stateanchor = "middle";
|
||
|
||
if (sensor.type == "accelerometer" ||
|
||
sensor.type == "gyroscope" ||
|
||
sensor.type == "magnetometer" ||
|
||
sensor.type == "stick")
|
||
{
|
||
if (context.compactLayout)
|
||
imgx = sensor.drawInfo.x + 5;
|
||
else
|
||
imgx = sensor.drawInfo.x - (imgw / 4) + (sensor.drawInfo.width / 4);
|
||
|
||
state1x = (imgx + imgw) + 10;
|
||
state1y = imgy;
|
||
stateanchor = 'start';
|
||
}
|
||
|
||
|
||
var portx = state1x;
|
||
var porty = imgy;
|
||
|
||
var namex = sensor.drawInfo.x + (sensor.drawInfo.width / 2);
|
||
var namey = sensor.drawInfo.y + (imgh * 0.20);
|
||
var nameanchor = "middle";
|
||
|
||
var portsize = sensor.drawInfo.height * 0.11;
|
||
|
||
if (context.compactLayout)
|
||
var statesize = sensor.drawInfo.height * 0.14;
|
||
else
|
||
var statesize = sensor.drawInfo.height * 0.10;
|
||
|
||
var namesize = sensor.drawInfo.height * 0.15;
|
||
|
||
|
||
|
||
var drawPortText = true;
|
||
var drawName = true;
|
||
|
||
drawPortText = false;
|
||
|
||
if (!sensor.focusrect || isElementRemoved(sensor.focusrect))
|
||
sensor.focusrect = paper.rect(imgx, imgy, imgw, imgh);
|
||
|
||
sensor.focusrect.attr({
|
||
"fill": "468DDF",
|
||
"fill-opacity": 0,
|
||
"opacity": 0,
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
if (context.autoGrading) {
|
||
|
||
scrolloffset = $('#virtualSensors').scrollLeft();
|
||
|
||
if (scrolloffset > 0)
|
||
fadeopacity = 0.3;
|
||
|
||
imgw = sensor.drawInfo.width * .80;
|
||
imgh = sensor.drawInfo.height * .80;
|
||
|
||
imgx = sensor.drawInfo.x + (imgw * 0.75) + scrolloffset;
|
||
imgy = sensor.drawInfo.y + (sensor.drawInfo.height / 2) - (imgh / 2);
|
||
|
||
state1x = imgx + imgw * 1.2;
|
||
state1y = imgy + (imgh / 2);
|
||
|
||
portx = sensor.drawInfo.x;
|
||
porty = imgy + (imgh / 2);
|
||
|
||
portsize = imgh / 3;
|
||
statesize = sensor.drawInfo.height * 0.2;
|
||
|
||
namex = portx;
|
||
namesize = portsize;
|
||
nameanchor = "start";
|
||
}
|
||
|
||
|
||
if (sensor.type == "led") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 0;
|
||
|
||
if (!sensor.ledoff || isElementRemoved(sensor.ledoff)) {
|
||
sensor.ledoff = paper.image(getImg('ledoff.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.focusrect.click(function () {
|
||
if (!context.autoGrading && (!context.runner || !context.runner.isRunning())) {
|
||
sensor.state = !sensor.state;
|
||
drawSensor(sensor);
|
||
} else {
|
||
actuatorsInRunningModeError();
|
||
}
|
||
});
|
||
}
|
||
|
||
if (!sensor.ledon || isElementRemoved(sensor.ledon)) {
|
||
var imagename = "ledon-";
|
||
if (sensor.subType)
|
||
imagename += sensor.subType;
|
||
else
|
||
imagename += "red";
|
||
|
||
imagename += ".png";
|
||
|
||
sensor.ledon = paper.image(getImg(imagename), imgx, imgy, imgw, imgh);
|
||
}
|
||
|
||
|
||
sensor.ledon.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
sensor.ledoff.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
if (sensor.showAsAnalog)
|
||
{
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state);
|
||
}
|
||
else
|
||
{
|
||
if (sensor.state) {
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.on.toUpperCase());
|
||
} else {
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.off.toUpperCase());
|
||
}
|
||
}
|
||
|
||
if (sensor.state) {
|
||
sensor.ledon.attr({ "opacity": fadeopacity });
|
||
sensor.ledoff.attr({ "opacity": 0 });
|
||
} else {
|
||
sensor.ledon.attr({ "opacity": 0 });
|
||
sensor.ledoff.attr({ "opacity": fadeopacity });
|
||
}
|
||
|
||
var x = typeof sensor.state;
|
||
|
||
if(typeof sensor.state == 'number' ) {
|
||
sensor.ledon.attr({ "opacity": sensor.state * fadeopacity });
|
||
sensor.ledoff.attr({ "opacity": fadeopacity });
|
||
}
|
||
|
||
|
||
if ((!context.runner || !context.runner.isRunning())
|
||
&& !context.offLineMode) {
|
||
|
||
findSensorDefinition(sensor).setLiveState(sensor, sensor.state, function(x) {});
|
||
}
|
||
|
||
} else if (sensor.type == "buzzer") {
|
||
|
||
if(typeof sensor.state == 'number' &&
|
||
sensor.state != 0 &&
|
||
sensor.state != 1) {
|
||
buzzerSound.start(sensor.name, sensor.state);
|
||
} else if (sensor.state) {
|
||
buzzerSound.start(sensor.name);
|
||
} else {
|
||
buzzerSound.stop(sensor.name);
|
||
}
|
||
|
||
if(!juststate) {
|
||
if(sensor.muteBtn) {
|
||
sensor.muteBtn.remove();
|
||
}
|
||
|
||
|
||
var muteBtnSize = sensor.drawInfo.width * 0.15;
|
||
sensor.muteBtn = paper.text(
|
||
imgx + imgw,
|
||
imgy + (imgh / 2),
|
||
buzzerSound.isMuted(sensor.name) ? "\uf6a9" : "\uf028"
|
||
);
|
||
sensor.muteBtn.node.style.fontWeight = "bold";
|
||
sensor.muteBtn.node.style.cursor = "default";
|
||
sensor.muteBtn.node.style.MozUserSelect = "none";
|
||
sensor.muteBtn.node.style.WebkitUserSelect = "none";
|
||
sensor.muteBtn.attr({
|
||
"font-size": muteBtnSize + "px",
|
||
fill: buzzerSound.isMuted(sensor.name) ? "lightgray" : "#468DDF",
|
||
"font-family": '"Font Awesome 5 Free"',
|
||
'text-anchor': 'start'
|
||
});
|
||
sensor.muteBtn.click(function () {
|
||
if(buzzerSound.isMuted(sensor.name)) {
|
||
buzzerSound.unmute(sensor.name)
|
||
} else {
|
||
buzzerSound.mute(sensor.name)
|
||
}
|
||
drawSensor(sensor);
|
||
});
|
||
}
|
||
|
||
|
||
if (!sensor.buzzeron || isElementRemoved(sensor.buzzeron))
|
||
sensor.buzzeron = paper.image(getImg('buzzer-ringing.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.buzzeroff || isElementRemoved(sensor.buzzeroff)) {
|
||
sensor.buzzeroff = paper.image(getImg('buzzer.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.focusrect.click(function () {
|
||
if (!context.autoGrading && (!context.runner || !context.runner.isRunning())) {
|
||
sensor.state = !sensor.state;
|
||
drawSensor(sensor);
|
||
} else {
|
||
actuatorsInRunningModeError();
|
||
}
|
||
});
|
||
}
|
||
|
||
if (sensor.state) {
|
||
if (!sensor.buzzerInterval) {
|
||
sensor.buzzerInterval = setInterval(function () {
|
||
|
||
if (!sensor.removed) {
|
||
sensor.ringingState = !sensor.ringingState;
|
||
drawSensor(sensor, true, true);
|
||
} else {
|
||
clearInterval(sensor.buzzerInterval);
|
||
}
|
||
|
||
}, 100);
|
||
}
|
||
} else {
|
||
if (sensor.buzzerInterval) {
|
||
clearInterval(sensor.buzzerInterval);
|
||
sensor.buzzerInterval = null;
|
||
sensor.ringingState = null;
|
||
}
|
||
}
|
||
sensor.buzzeron.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
sensor.buzzeroff.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
var drawState = sensor.state;
|
||
if (sensor.ringingState != null)
|
||
drawState = sensor.ringingState;
|
||
|
||
if (drawState) {
|
||
sensor.buzzeron.attr({ "opacity": fadeopacity });
|
||
sensor.buzzeroff.attr({ "opacity": 0 });
|
||
|
||
|
||
} else {
|
||
sensor.buzzeron.attr({ "opacity": 0 });
|
||
sensor.buzzeroff.attr({ "opacity": fadeopacity });
|
||
}
|
||
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
var stateText = findSensorDefinition(sensor).getStateString(sensor.state);
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, stateText);
|
||
|
||
|
||
if ((!context.runner || !context.runner.isRunning())
|
||
&& !context.offLineMode) {
|
||
|
||
var setLiveState = findSensorDefinition(sensor).setLiveState;
|
||
|
||
if (setLiveState) {
|
||
setLiveState(sensor, sensor.state, function(x) {});
|
||
}
|
||
}
|
||
|
||
} else if (sensor.type == "button") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.buttonon || isElementRemoved(sensor.buttonon))
|
||
sensor.buttonon = paper.image(getImg('buttonon.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.buttonoff || isElementRemoved(sensor.buttonoff))
|
||
sensor.buttonoff = paper.image(getImg('buttonoff.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = false;
|
||
|
||
sensor.buttonon.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
sensor.buttonoff.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
if (sensor.state) {
|
||
sensor.buttonon.attr({ "opacity": fadeopacity });
|
||
sensor.buttonoff.attr({ "opacity": 0 });
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.on.toUpperCase());
|
||
} else {
|
||
sensor.buttonon.attr({ "opacity": 0 });
|
||
sensor.buttonoff.attr({ "opacity": fadeopacity });
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.off.toUpperCase());
|
||
}
|
||
|
||
if (!context.autoGrading && !sensor.buttonon.node.onmousedown) {
|
||
sensor.focusrect.node.onmousedown = function () {
|
||
if (context.offLineMode) {
|
||
sensor.state = true;
|
||
drawSensor(sensor);
|
||
} else
|
||
sensorInConnectedModeError();
|
||
};
|
||
|
||
|
||
sensor.focusrect.node.onmouseup = function () {
|
||
if (context.offLineMode) {
|
||
sensor.state = false;
|
||
sensor.wasPressed = true;
|
||
drawSensor(sensor);
|
||
|
||
if (sensor.onPressed)
|
||
sensor.onPressed();
|
||
} else
|
||
sensorInConnectedModeError();
|
||
}
|
||
|
||
sensor.focusrect.node.ontouchstart = sensor.focusrect.node.onmousedown;
|
||
sensor.focusrect.node.ontouchend = sensor.focusrect.node.onmouseup;
|
||
}
|
||
} else if (sensor.type == "screen") {
|
||
if (sensor.stateText) {
|
||
sensor.stateText.remove();
|
||
sensor.stateText = null;
|
||
}
|
||
|
||
var borderSize = 5;
|
||
|
||
var screenScale = 2;
|
||
if(sensor.drawInfo.width < 300) {
|
||
screenScale = 1;
|
||
}
|
||
if(sensor.drawInfo.width < 150) {
|
||
screenScale = 0.5;
|
||
}
|
||
|
||
var screenScalerSize = {
|
||
width: 128 * screenScale,
|
||
height: 32 * screenScale
|
||
}
|
||
borderSize = borderSize * screenScale;
|
||
|
||
imgw = screenScalerSize.width + borderSize * 2;
|
||
imgh = screenScalerSize.height + borderSize * 2;
|
||
imgx = sensor.drawInfo.x - (imgw / 2) + (sensor.drawInfo.width / 2);
|
||
|
||
imgy = sensor.drawInfo.y + Math.max(0, (sensor.drawInfo.height - imgh) * 0.5);
|
||
|
||
portx = imgx + imgw + borderSize;
|
||
porty = imgy + imgh / 3;
|
||
/*
|
||
if (context.autoGrading) {
|
||
state1x = imgx + imgw;
|
||
state1y = imgy + (imgh / 2);
|
||
|
||
portsize = imgh / 4;
|
||
statesize = imgh / 6;
|
||
}
|
||
*/
|
||
statesize = imgh / 3.5;
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img)) {
|
||
sensor.img = paper.image(getImg('screen.png'), imgx, imgy, imgw, imgh);
|
||
}
|
||
|
||
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
|
||
if (sensor.state) {
|
||
if (sensor.state.isDrawingData) {
|
||
if (!sensor.screenrect ||
|
||
isElementRemoved(sensor.screenrect) ||
|
||
!sensor.canvasNode) {
|
||
sensor.screenrect = paper.rect(imgx, imgy, screenScalerSize.width, screenScalerSize.height);
|
||
|
||
sensor.canvasNode = document.createElementNS("http://www.w3.org/2000/svg", 'foreignObject');
|
||
sensor.canvasNode.setAttribute("x",imgx + borderSize); //Set rect data
|
||
sensor.canvasNode.setAttribute("y",imgy + borderSize); //Set rect data
|
||
sensor.canvasNode.setAttribute("width", screenScalerSize.width); //Set rect data
|
||
sensor.canvasNode.setAttribute("height", screenScalerSize.height); //Set rect data
|
||
paper.canvas.appendChild(sensor.canvasNode);
|
||
|
||
sensor.canvas = document.createElement("canvas");
|
||
sensor.canvas.id = "screencanvas";
|
||
sensor.canvas.width = screenScalerSize.width;
|
||
sensor.canvas.height = screenScalerSize.height;
|
||
sensor.canvasNode.appendChild(sensor.canvas);
|
||
}
|
||
|
||
$(sensor.canvas).css({ opacity: fadeopacity });
|
||
sensor.canvasNode.setAttribute("x", imgx + borderSize); //Set rect data
|
||
sensor.canvasNode.setAttribute("y", imgy + borderSize); //Set rect data
|
||
sensor.canvasNode.setAttribute("width", screenScalerSize.width); //Set rect data
|
||
sensor.canvasNode.setAttribute("height", screenScalerSize.height); //Set rect data
|
||
|
||
sensor.screenrect.attr({
|
||
"x": imgx + borderSize,
|
||
"y": imgy + borderSize,
|
||
"width": 128,
|
||
"height": 32,
|
||
});
|
||
|
||
sensor.screenrect.attr({ "opacity": 0 });
|
||
|
||
context.initScreenDrawing(sensor);
|
||
//sensor.screenDrawing.copyToCanvas(sensor.canvas, screenScale);
|
||
screenDrawing.renderToCanvas(sensor.state, sensor.canvas, screenScale);
|
||
} else {
|
||
var statex = imgx + (imgw * .05);
|
||
|
||
var statey = imgy + (imgh * .2);
|
||
|
||
if (sensor.state.line1.length > 16)
|
||
sensor.state.line1 = sensor.state.line1.substring(0, 16);
|
||
|
||
if (sensor.state.line2 && sensor.state.line2.length > 16)
|
||
sensor.state.line2 = sensor.state.line2.substring(0, 16);
|
||
|
||
if (sensor.canvasNode) {
|
||
$(sensor.canvasNode).remove();
|
||
sensor.canvasNode = null;
|
||
}
|
||
|
||
sensor.stateText = paper.text(statex, statey, sensor.state.line1 + "\n" + (sensor.state.line2 ? sensor.state.line2 : ""));
|
||
stateanchor = "start";
|
||
sensor.stateText.attr("")
|
||
}
|
||
}
|
||
} else if (sensor.type == "temperature") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 25; // FIXME
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('temperature-cold.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.img2 || isElementRemoved(sensor.img2))
|
||
sensor.img2 = paper.image(getImg('temperature-hot.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.img3 || isElementRemoved(sensor.img3))
|
||
sensor.img3 = paper.image(getImg('temperature-overlay.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
|
||
});
|
||
sensor.img2.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
sensor.img3.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
var scale = imgh / 60;
|
||
|
||
var cliph = scale * sensor.state;
|
||
|
||
sensor.img2.attr({
|
||
"clip-rect":
|
||
imgx + "," +
|
||
(imgy + imgh - cliph) + "," +
|
||
(imgw) + "," +
|
||
cliph
|
||
});
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + " °C");
|
||
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 60);
|
||
}
|
||
else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
|
||
} else if (sensor.type == "servo") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('servo.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.pale || isElementRemoved(sensor.pale))
|
||
sensor.pale = paper.image(getImg('servo-pale.png'), imgx, imgy, imgw, imgh);
|
||
|
||
|
||
if (!sensor.center || isElementRemoved(sensor.center))
|
||
sensor.center = paper.image(getImg('servo-center.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
sensor.pale.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"transform": "",
|
||
"opacity": fadeopacity,
|
||
});
|
||
sensor.center.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
sensor.pale.rotate(sensor.state);
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 0;
|
||
|
||
sensor.state = Math.round(sensor.state);
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + "°");
|
||
|
||
if ((!context.runner || !context.runner.isRunning())
|
||
&& !context.offLineMode) {
|
||
if (!sensor.updatetimeout) {
|
||
sensor.updatetimeout = setTimeout(function () {
|
||
|
||
findSensorDefinition(sensor).setLiveState(sensor, sensor.state, function(x) {});
|
||
|
||
sensor.updatetimeout = null;
|
||
}, 100);
|
||
}
|
||
}
|
||
|
||
if (!context.autoGrading &&
|
||
(!context.runner || !context.runner.isRunning())) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 180);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
} else if (sensor.type == "potentiometer") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('potentiometer.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.pale || isElementRemoved(sensor.pale))
|
||
sensor.pale = paper.image(getImg('potentiometer-pale.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
sensor.pale.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"transform": "",
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 0;
|
||
|
||
sensor.pale.rotate(sensor.state * 3.6);
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + "%");
|
||
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 100);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
|
||
} else if (sensor.type == "range") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('range.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 500;
|
||
|
||
if (sensor.rangedistance)
|
||
sensor.rangedistance.remove();
|
||
|
||
if (sensor.rangedistancestart)
|
||
sensor.rangedistancestart.remove();
|
||
|
||
if (sensor.rangedistanceend)
|
||
sensor.rangedistanceend.remove();
|
||
|
||
var rangew;
|
||
|
||
if (sensor.state < 30) {
|
||
rangew = imgw * sensor.state / 100;
|
||
} else {
|
||
var firstpart = imgw * 30 / 100;
|
||
var remaining = imgw - firstpart;
|
||
|
||
rangew = firstpart + (remaining * (sensor.state) * 0.0015);
|
||
}
|
||
|
||
var centerx = imgx + (imgw / 2);
|
||
|
||
sensor.rangedistance = paper.path(["M", centerx - (rangew / 2),
|
||
imgy + imgw,
|
||
"L", centerx + (rangew / 2),
|
||
imgy + imgw]);
|
||
|
||
var markh = 16;
|
||
|
||
sensor.rangedistancestart = paper.path(["M", centerx - (rangew / 2),
|
||
imgy + imgw - (markh / 2),
|
||
"L", centerx - (rangew / 2),
|
||
imgy + imgw + (markh / 2)]);
|
||
|
||
sensor.rangedistanceend = paper.path(["M", centerx + (rangew / 2),
|
||
imgy + imgw - (markh / 2),
|
||
"L", centerx + (rangew / 2),
|
||
imgy + imgw + (markh / 2)]);
|
||
|
||
sensor.rangedistance.attr({
|
||
"stroke-width": 4,
|
||
"stroke": "#468DDF",
|
||
"stroke-linecapstring": "round"
|
||
});
|
||
|
||
sensor.rangedistancestart.attr({
|
||
"stroke-width": 4,
|
||
"stroke": "#468DDF",
|
||
"stroke-linecapstring": "round"
|
||
});
|
||
|
||
|
||
sensor.rangedistanceend.attr({
|
||
"stroke-width": 4,
|
||
"stroke": "#468DDF",
|
||
"stroke-linecapstring": "round"
|
||
});
|
||
|
||
if (sensor.state >= 10)
|
||
sensor.state = Math.round(sensor.state);
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + " cm");
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 500);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
} else if (sensor.type == "light") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('light.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.moon || isElementRemoved(sensor.moon))
|
||
sensor.moon = paper.image(getImg('light-moon.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.sun || isElementRemoved(sensor.sun))
|
||
sensor.sun = paper.image(getImg('light-sun.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 0;
|
||
|
||
if (sensor.state > 50) {
|
||
var opacity = (sensor.state - 50) * 0.02;
|
||
sensor.sun.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": opacity * .80 * fadeopacity
|
||
});
|
||
sensor.moon.attr({ "opacity": 0 });
|
||
}
|
||
else {
|
||
var opacity = (50 - sensor.state) * 0.02;
|
||
sensor.moon.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": opacity * .80 * fadeopacity
|
||
});
|
||
sensor.sun.attr({ "opacity": 0 });
|
||
}
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + "%");
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 100);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
} else if (sensor.type == "humidity") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('humidity.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 0;
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + "%");
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 100);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
} else if (sensor.type == "accelerometer") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('accel.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.state)
|
||
{
|
||
sensor.state = [0, 0, 1];
|
||
}
|
||
|
||
if (sensor.state) {
|
||
try {
|
||
sensor.stateText = paper.text(state1x, state1y, "X: " + sensor.state[0] + " m/s²\nY: " + sensor.state[1] + " m/s²\nZ: " + sensor.state[2] + " m/s²");
|
||
} catch (Err)
|
||
{
|
||
var a = 1;
|
||
}
|
||
}
|
||
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, -8 * 9.81, 8 * 9.81);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
} else if (sensor.type == "gyroscope") {
|
||
if (!sensor.state) {
|
||
sensor.state = [0, 0, 0];
|
||
}
|
||
if (sensor.stateText) {
|
||
sensor.stateText.remove();
|
||
}
|
||
sensor.stateText = paper.text(state1x, state1y, "X: " + sensor.state[0] + "°/s\nY: " + sensor.state[1] + "°/s\nZ: " + sensor.state[2] + "°/s");
|
||
if (!sensor.previousState)
|
||
sensor.previousState = [0, 0, 0];
|
||
|
||
if (sensor.rotationAngles != undefined) {
|
||
|
||
// update the rotation angle
|
||
for (var i = 0; i < 3; i++)
|
||
sensor.rotationAngles[i] += sensor.previousState[i] * ((new Date() - sensor.lastSpeedChange) / 1000);
|
||
|
||
sensor.lastSpeedChange = new Date();
|
||
}
|
||
|
||
|
||
sensor.previousState = sensor.state;
|
||
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
var img3d = gyroscope3D.getInstance(imgw, imgh);
|
||
}
|
||
if(img3d) {
|
||
if (!sensor.screenrect || isElementRemoved(sensor.screenrect)) {
|
||
sensor.screenrect = paper.rect(imgx, imgy, imgw, imgh);
|
||
sensor.screenrect.attr({ "opacity": 0 });
|
||
|
||
sensor.canvasNode = document.createElementNS("http://www.w3.org/2000/svg", 'foreignObject');
|
||
sensor.canvasNode.setAttribute("x", imgx);
|
||
sensor.canvasNode.setAttribute("y", imgy);
|
||
sensor.canvasNode.setAttribute("width", imgw);
|
||
sensor.canvasNode.setAttribute("height", imgh);
|
||
paper.canvas.appendChild(sensor.canvasNode);
|
||
|
||
sensor.canvas = document.createElement("canvas");
|
||
sensor.canvas.width = imgw;
|
||
sensor.canvas.height = imgh;
|
||
sensor.canvasNode.appendChild(sensor.canvas);
|
||
}
|
||
|
||
var sensorCtx = sensor.canvas.getContext('2d');
|
||
sensorCtx.clearRect(0, 0, imgw, imgh);
|
||
|
||
sensorCtx.drawImage(img3d.render(
|
||
sensor.state[0],
|
||
sensor.state[2],
|
||
sensor.state[1]
|
||
), 0, 0);
|
||
|
||
if(!juststate) {
|
||
sensor.focusrect.drag(
|
||
function(dx, dy, x, y, event) {
|
||
sensor.state[0] = Math.max(-125, Math.min(125, sensor.old_state[0] + dy));
|
||
sensor.state[1] = Math.max(-125, Math.min(125, sensor.old_state[1] - dx));
|
||
drawSensor(sensor, true)
|
||
},
|
||
function() {
|
||
sensor.old_state = sensor.state.slice();
|
||
}
|
||
);
|
||
}
|
||
|
||
} else {
|
||
if (!sensor.img || isElementRemoved(sensor.img)) {
|
||
sensor.img = paper.image(getImg('gyro.png'), imgx, imgy, imgw, imgh);
|
||
}
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, -125, 125);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
}
|
||
} else if (sensor.type == "magnetometer") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('mag.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.needle || isElementRemoved(sensor.needle))
|
||
sensor.needle = paper.image(getImg('mag-needle.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
sensor.needle.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"transform": "",
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
if (!sensor.state)
|
||
{
|
||
sensor.state = [0, 0, 0];
|
||
}
|
||
|
||
if (sensor.state) {
|
||
var heading = Math.atan2(sensor.state[0],sensor.state[1])*(180/Math.PI) + 180;
|
||
|
||
sensor.needle.rotate(heading);
|
||
}
|
||
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (sensor.state) {
|
||
sensor.stateText = paper.text(state1x, state1y, "X: " + sensor.state[0] + " μT\nY: " + sensor.state[1] + " μT\nZ: " + sensor.state[2] + " μT");
|
||
}
|
||
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, -1600, 1600);
|
||
} else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
} else if (sensor.type == "sound") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (sensor.state == null)
|
||
sensor.state = 25; // FIXME
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('sound.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
// if we just do sensor.state, if it is equal to 0 then the state is not displayed
|
||
if (sensor.state != null) {
|
||
sensor.stateText = paper.text(state1x, state1y, sensor.state + " dB");
|
||
}
|
||
|
||
if (!context.autoGrading && context.offLineMode) {
|
||
setSlider(sensor, juststate, imgx, imgy, imgw, imgh, 0, 60);
|
||
}
|
||
else {
|
||
sensor.focusrect.click(function () {
|
||
sensorInConnectedModeError();
|
||
});
|
||
|
||
removeSlider(sensor);
|
||
}
|
||
|
||
} else if (sensor.type == "irtrans") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.ledon || isElementRemoved(sensor.ledon)) {
|
||
sensor.ledon = paper.image(getImg("irtranson.png"), imgx, imgy, imgw, imgh);
|
||
}
|
||
|
||
if (!sensor.ledoff || isElementRemoved(sensor.ledoff)) {
|
||
sensor.ledoff = paper.image(getImg('irtransoff.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.focusrect.click(function () {
|
||
if (!context.autoGrading && (!context.runner || !context.runner.isRunning())
|
||
&& !context.offLineMode) {
|
||
//sensor.state = !sensor.state;
|
||
//drawSensor(sensor);
|
||
window.displayHelper.showPopupDialog(irRemoteDialog);
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
$('#picancel2').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
var addedSomeButtons = false;
|
||
var remotecontent = document.getElementById('piremotecontent');
|
||
var parentdiv = document.createElement("DIV");
|
||
parentdiv.className = "form-group";
|
||
|
||
remotecontent.appendChild(parentdiv);
|
||
var count = 0;
|
||
for (var code in context.remoteIRcodes)
|
||
{
|
||
addedSomeButtons = true;
|
||
context.remoteIRcodes[code];
|
||
|
||
var btn = document.createElement("BUTTON");
|
||
var t = document.createTextNode(code);
|
||
|
||
btn.className = "btn";
|
||
btn.appendChild(t);
|
||
parentdiv.appendChild(btn);
|
||
|
||
let capturedcode = code;
|
||
let captureddata = context.remoteIRcodes[code];
|
||
btn.onclick = function() {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
//if (sensor.waitingForIrMessage)
|
||
//sensor.waitingForIrMessage(capturedcode);
|
||
|
||
context.quickPiConnection.sendCommand("presetIRMessage(\"" + capturedcode + "\", '" + captureddata + "')", function(returnVal) {});
|
||
context.quickPiConnection.sendCommand("sendIRMessage(\"irtran1\", \"" + capturedcode + "\")", function(returnVal) {});
|
||
|
||
};
|
||
|
||
count += 1;
|
||
|
||
if (count == 4)
|
||
{
|
||
count = 0;
|
||
parentdiv = document.createElement("DIV");
|
||
parentdiv.className = "form-group";
|
||
remotecontent.appendChild(parentdiv);
|
||
}
|
||
}
|
||
if (!addedSomeButtons)
|
||
{
|
||
$('#piremotemessage').text(strings.messages.noIrPresets);
|
||
}
|
||
|
||
var btn = document.createElement("BUTTON");
|
||
|
||
if (sensor.state)
|
||
var t = document.createTextNode(strings.messages.irDisableContinous);
|
||
else
|
||
var t = document.createTextNode(strings.messages.irEnableContinous);
|
||
|
||
|
||
btn.className = "btn";
|
||
btn.appendChild(t);
|
||
parentdiv.appendChild(btn);
|
||
btn.onclick = function() {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
sensor.state = !sensor.state;
|
||
drawSensor(sensor);
|
||
};
|
||
} else {
|
||
actuatorsInRunningModeError();
|
||
}
|
||
});
|
||
}
|
||
|
||
sensor.ledon.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
sensor.ledoff.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
if (sensor.state) {
|
||
sensor.ledon.attr({ "opacity": fadeopacity });
|
||
sensor.ledoff.attr({ "opacity": 0 });
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.on.toUpperCase());
|
||
} else {
|
||
sensor.ledon.attr({ "opacity": 0 });
|
||
sensor.ledoff.attr({ "opacity": fadeopacity });
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.off.toUpperCase());
|
||
}
|
||
|
||
|
||
if ((!context.runner || !context.runner.isRunning())
|
||
&& !context.offLineMode) {
|
||
|
||
findSensorDefinition(sensor).setLiveState(sensor, sensor.state, function(x) {});
|
||
}
|
||
} else if (sensor.type == "irrecv") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.buttonon || isElementRemoved(sensor.buttonon))
|
||
sensor.buttonon = paper.image(getImg('irrecvon.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.buttonoff || isElementRemoved(sensor.buttonoff))
|
||
sensor.buttonoff = paper.image(getImg('irrecvoff.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.buttonon.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
sensor.buttonoff.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
if (sensor.state) {
|
||
sensor.buttonon.attr({ "opacity": fadeopacity });
|
||
sensor.buttonoff.attr({ "opacity": 0 });
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.on.toUpperCase());
|
||
} else {
|
||
sensor.buttonon.attr({ "opacity": 0 });
|
||
sensor.buttonoff.attr({ "opacity": fadeopacity });
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, strings.messages.off.toUpperCase());
|
||
}
|
||
|
||
sensor.focusrect.click(function () {
|
||
if (context.offLineMode) {
|
||
window.displayHelper.showPopupDialog(irRemoteDialog);
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
$('#picancel2').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
var addedSomeButtons = false;
|
||
var remotecontent = document.getElementById('piremotecontent');
|
||
var parentdiv = document.createElement("DIV");
|
||
parentdiv.className = "form-group";
|
||
|
||
remotecontent.appendChild(parentdiv);
|
||
var count = 0;
|
||
for (var code in context.remoteIRcodes)
|
||
{
|
||
addedSomeButtons = true;
|
||
context.remoteIRcodes[code];
|
||
|
||
var btn = document.createElement("BUTTON");
|
||
var t = document.createTextNode(code);
|
||
|
||
btn.className = "btn";
|
||
btn.appendChild(t);
|
||
parentdiv.appendChild(btn);
|
||
|
||
let capturedcode = code;
|
||
btn.onclick = function() {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
if (sensor.waitingForIrMessage)
|
||
sensor.waitingForIrMessage(capturedcode);
|
||
};
|
||
|
||
count += 1;
|
||
|
||
if (count == 4)
|
||
{
|
||
count = 0;
|
||
parentdiv = document.createElement("DIV");
|
||
parentdiv.className = "form-group";
|
||
remotecontent.appendChild(parentdiv);
|
||
}
|
||
}
|
||
if (!addedSomeButtons)
|
||
{
|
||
$('#piremotemessage').text(strings.messages.noIrPresets);
|
||
}
|
||
|
||
var btn = document.createElement("BUTTON");
|
||
|
||
if (sensor.state)
|
||
var t = document.createTextNode(strings.messages.irDisableContinous);
|
||
else
|
||
var t = document.createTextNode(strings.messages.irEnableContinous);
|
||
|
||
|
||
btn.className = "btn";
|
||
btn.appendChild(t);
|
||
parentdiv.appendChild(btn);
|
||
btn.onclick = function() {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
|
||
sensor.state = !sensor.state;
|
||
drawSensor(sensor);
|
||
};
|
||
|
||
}
|
||
else{
|
||
//sensorInConnectedModeError();
|
||
|
||
context.stopLiveUpdate = true;
|
||
|
||
var irLearnDialog = "<div class=\"content qpi\">" +
|
||
" <div class=\"panel-heading\">" +
|
||
" <h2 class=\"sectionTitle\">" +
|
||
" <span class=\"iconTag\"><i class=\"icon fas fa-list-ul\"></i></span>" +
|
||
strings.messages.irReceiverTitle +
|
||
" </h2>" +
|
||
" <div class=\"exit\" id=\"picancel\"><i class=\"icon fas fa-times\"></i></div>" +
|
||
" </div>" +
|
||
" <div id=\"sensorPicker\" class=\"panel-body\">" +
|
||
" <div class=\"form-group\">" +
|
||
" <p>" + strings.messages.directIrControl + "</p>" +
|
||
" </div>" +
|
||
" <div class=\"form-group\">" +
|
||
" <p id=piircode></p>" +
|
||
" </div>" +
|
||
" </div>" +
|
||
" <div class=\"singleButton\">" +
|
||
" <button id=\"piirlearn\" class=\"btn\"><i class=\"fa fa-wifi icon\"></i>" + strings.messages.getIrCode + "</button>" +
|
||
" <button id=\"picancel2\" class=\"btn\"><i class=\"fa fa-times icon\"></i>" + strings.messages.closeDialog + "</button>" +
|
||
" </div>" +
|
||
"</div>";
|
||
|
||
window.displayHelper.showPopupDialog(irLearnDialog);
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
context.stopLiveUpdate = false;
|
||
});
|
||
|
||
$('#picancel2').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
context.stopLiveUpdate = false;
|
||
});
|
||
|
||
$('#piirlearn').click(function () {
|
||
|
||
$('#piirlearn').attr('disabled', true);
|
||
|
||
$("#piircode").text("");
|
||
context.quickPiConnection.sendCommand("readIRMessageCode(\"irrec1\", 10000)", function(retval)
|
||
{
|
||
$('#piirlearn').attr('disabled', false);
|
||
$("#piircode").text(retval);
|
||
});
|
||
});
|
||
|
||
}
|
||
});
|
||
/*
|
||
if (!context.autoGrading && !sensor.buttonon.node.onmousedown) {
|
||
sensor.focusrect.node.onmousedown = function () {
|
||
if (context.offLineMode) {
|
||
sensor.state = true;
|
||
drawSensor(sensor);
|
||
} else
|
||
sensorInConnectedModeError();
|
||
};
|
||
|
||
|
||
sensor.focusrect.node.onmouseup = function () {
|
||
if (context.offLineMode) {
|
||
sensor.state = false;
|
||
drawSensor(sensor);
|
||
|
||
if (sensor.onPressed)
|
||
sensor.onPressed();
|
||
} else
|
||
sensorInConnectedModeError();
|
||
}
|
||
|
||
sensor.focusrect.node.ontouchstart = sensor.focusrect.node.onmousedown;
|
||
sensor.focusrect.node.ontouchend = sensor.focusrect.node.onmouseup;
|
||
}*/
|
||
} else if (sensor.type == "stick") {
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('stick.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.imgup || isElementRemoved(sensor.imgup))
|
||
sensor.imgup = paper.image(getImg('stickup.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.imgdown || isElementRemoved(sensor.imgdown))
|
||
sensor.imgdown = paper.image(getImg('stickdown.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.imgleft || isElementRemoved(sensor.imgleft))
|
||
sensor.imgleft = paper.image(getImg('stickleft.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.imgright || isElementRemoved(sensor.imgright))
|
||
sensor.imgright = paper.image(getImg('stickright.png'), imgx, imgy, imgw, imgh);
|
||
|
||
if (!sensor.imgcenter || isElementRemoved(sensor.imgcenter))
|
||
sensor.imgcenter = paper.image(getImg('stickcenter.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": fadeopacity,
|
||
});
|
||
|
||
sensor.imgup.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": 0,
|
||
});
|
||
sensor.imgdown.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": 0,
|
||
});
|
||
sensor.imgleft.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": 0,
|
||
});
|
||
sensor.imgright.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": 0,
|
||
});
|
||
sensor.imgcenter.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": 0,
|
||
});
|
||
|
||
if (sensor.stateText)
|
||
sensor.stateText.remove();
|
||
|
||
if (!sensor.state)
|
||
sensor.state = [false, false, false, false, false];
|
||
|
||
var stateString = "\n";
|
||
if (sensor.state[0]) {
|
||
stateString += strings.messages.up.toUpperCase() + "\n";
|
||
sensor.imgup.attr({ "opacity": 1 });
|
||
}
|
||
if (sensor.state[1]) {
|
||
stateString += strings.messages.down.toUpperCase() + "\n";
|
||
sensor.imgdown.attr({ "opacity": 1 });
|
||
}
|
||
if (sensor.state[2]) {
|
||
stateString += strings.messages.left.toUpperCase() + "\n";
|
||
sensor.imgleft.attr({ "opacity": 1 });
|
||
}
|
||
if (sensor.state[3]) {
|
||
stateString += strings.messages.right.toUpperCase() + "\n";
|
||
sensor.imgright.attr({ "opacity": 1 });
|
||
}
|
||
if (sensor.state[4]) {
|
||
stateString += strings.messages.center.toUpperCase() + "\n";
|
||
sensor.imgcenter.attr({ "opacity": 1 });
|
||
}
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, stateString);
|
||
|
||
if (sensor.portText)
|
||
sensor.portText.remove();
|
||
|
||
drawPortText = false;
|
||
|
||
if (sensor.portText)
|
||
sensor.portText.remove();
|
||
|
||
if (!context.autoGrading) {
|
||
var gpios = findSensorDefinition(sensor).gpios;
|
||
var min = 255;
|
||
var max = 0;
|
||
|
||
for (var i = 0; i < gpios.length; i++) {
|
||
if (gpios[i] > max)
|
||
max = gpios[i];
|
||
|
||
if (gpios[i] < min)
|
||
min = gpios[i];
|
||
}
|
||
|
||
|
||
$('#stickupstate').text(sensor.state[0] ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase());
|
||
$('#stickdownstate').text(sensor.state[1] ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase());
|
||
$('#stickleftstate').text(sensor.state[2] ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase());
|
||
$('#stickrightstate').text(sensor.state[3] ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase());
|
||
$('#stickcenterstate').text(sensor.state[4] ? strings.messages.on.toUpperCase() : strings.messages.off.toUpperCase());
|
||
|
||
/*
|
||
sensor.portText = paper.text(state1x, state1y, "D" + min.toString() + "-D" + max.toString() + "?");
|
||
sensor.portText.attr({ "font-size": portsize + "px", 'text-anchor': 'start', fill: "blue" });
|
||
sensor.portText.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
var b = sensor.portText._getBBox();
|
||
sensor.portText.translate(0, b.height / 2);
|
||
|
||
var stickPortsDialog = `
|
||
<div class="content qpi">
|
||
<div class="panel-heading">
|
||
<h2 class="sectionTitle">
|
||
<span class="iconTag"><i class="icon fas fa-list-ul"></i></span>
|
||
Noms et ports de la manette
|
||
</h2>
|
||
<div class="exit" id="picancel"><i class="icon fas fa-times"></i></div>
|
||
</div>
|
||
<div id="sensorPicker" class="panel-body">
|
||
<label></label>
|
||
<div class="flex-container">
|
||
<table style="display:table-header-group;">
|
||
<tr>
|
||
<th>Name</th>
|
||
<th>Port</th>
|
||
<th>State</th>
|
||
<th>Direction</th>
|
||
</tr>
|
||
<tr>
|
||
<td><label id="stickupname"></td><td><label id="stickupport"></td><td><label id="stickupstate"></td><td><label id="stickupdirection"><i class="fas fa-arrow-up"></i></td>
|
||
</tr>
|
||
<tr>
|
||
<td><label id="stickdownname"></td><td><label id="stickdownport"></td><td><label id="stickdownstate"></td><td><label id="stickdowndirection"><i class="fas fa-arrow-down"></i></td>
|
||
</tr>
|
||
<tr>
|
||
<td><label id="stickleftname"></td><td><label id="stickleftport"></td><td><label id="stickleftstate"></td><td><label id="stickleftdirection"><i class="fas fa-arrow-left"></i></td>
|
||
</tr>
|
||
<tr>
|
||
<td><label id="stickrightname"></td><td><label id="stickrightport"></td><td><label id="stickrightstate"></td><td><label id="stickrightdirection"><i class="fas fa-arrow-right"></i></td>
|
||
</tr>
|
||
<tr>
|
||
<td><label id="stickcentername"></td><td><label id="stickcenterport"></td><td><label id="stickcenterstate"></td><td><label id="stickcenterdirection"><i class="fas fa-circle"></i></td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="singleButton">
|
||
<button id="picancel2" class="btn btn-centered"><i class="icon fa fa-check"></i>Fermer</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
sensor.portText.click(function () {
|
||
window.displayHelper.showPopupDialog(stickPortsDialog);
|
||
|
||
$('#picancel').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
$('#picancel2').click(function () {
|
||
$('#popupMessage').hide();
|
||
window.displayHelper.popupMessageShown = false;
|
||
});
|
||
|
||
$('#stickupname').text(sensor.name + ".up");
|
||
$('#stickdownname').text(sensor.name + ".down");
|
||
$('#stickleftname').text(sensor.name + ".left");
|
||
$('#stickrightname').text(sensor.name + ".right");
|
||
$('#stickcentername').text(sensor.name + ".center");
|
||
|
||
$('#stickupport').text("D" + gpios[0]);
|
||
$('#stickdownport').text("D" + gpios[1]);
|
||
$('#stickleftport').text("D" + gpios[2]);
|
||
$('#stickrightport').text("D" + gpios[3]);
|
||
$('#stickcenterport').text("D" + gpios[4]);
|
||
|
||
$('#stickupstate').text(sensor.state[0] ? "ON" : "OFF");
|
||
$('#stickdownstate').text(sensor.state[1] ? "ON" : "OFF");
|
||
$('#stickleftstate').text(sensor.state[2] ? "ON" : "OFF");
|
||
$('#stickrightstate').text(sensor.state[3] ? "ON" : "OFF");
|
||
$('#stickcenterstate').text(sensor.state[4] ? "ON" : "OFF");
|
||
|
||
});
|
||
*/
|
||
}
|
||
|
||
|
||
function poinInRect(rect, x, y) {
|
||
|
||
if (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
function moveRect(rect, x, y) {
|
||
rect.left += x;
|
||
rect.right += x;
|
||
|
||
rect.top += y;
|
||
rect.bottom += y;
|
||
}
|
||
|
||
sensor.focusrect.node.onmousedown = function(evt) {
|
||
if (!context.offLineMode) {
|
||
sensorInConnectedModeError();
|
||
return;
|
||
}
|
||
|
||
var e = evt.target;
|
||
var dim = e.getBoundingClientRect();
|
||
var rectsize = dim.width * .30;
|
||
|
||
|
||
var rect = {
|
||
left: dim.left,
|
||
right: dim.left + rectsize,
|
||
top: dim.top,
|
||
bottom: dim.top + rectsize,
|
||
}
|
||
|
||
// Up left
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[0] = true;
|
||
sensor.state[2] = true;
|
||
}
|
||
|
||
// Up
|
||
moveRect(rect, rectsize, 0);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[0] = true;
|
||
}
|
||
|
||
// Up right
|
||
moveRect(rect, rectsize, 0);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[0] = true;
|
||
sensor.state[3] = true;
|
||
}
|
||
|
||
// Right
|
||
moveRect(rect, 0, rectsize);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[3] = true;
|
||
}
|
||
|
||
// Center
|
||
moveRect(rect, -rectsize, 0);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[4] = true;
|
||
}
|
||
|
||
// Left
|
||
moveRect(rect, -rectsize, 0);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[2] = true;
|
||
}
|
||
|
||
// Down left
|
||
moveRect(rect, 0, rectsize);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[1] = true;
|
||
sensor.state[2] = true;
|
||
}
|
||
|
||
// Down
|
||
moveRect(rect, rectsize, 0);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[1] = true;
|
||
}
|
||
|
||
// Down right
|
||
moveRect(rect, rectsize, 0);
|
||
if (poinInRect(rect, evt.clientX, evt.clientY)) {
|
||
sensor.state[1] = true;
|
||
sensor.state[3] = true;
|
||
}
|
||
|
||
drawSensor(sensor);
|
||
}
|
||
|
||
sensor.focusrect.node.onmouseup = function(evt) {
|
||
if (!context.offLineMode) {
|
||
sensorInConnectedModeError();
|
||
return;
|
||
}
|
||
|
||
sensor.state = [false, false, false, false, false];
|
||
drawSensor(sensor);
|
||
}
|
||
|
||
sensor.focusrect.node.ontouchstart = sensor.focusrect.node.onmousedown;
|
||
sensor.focusrect.node.ontouchend = sensor.focusrect.node.onmouseup;
|
||
} else if (sensor.type == "cloudstore") {
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('cloudstore.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
"opacity": scrolloffset ? 0.3 : 1,
|
||
});
|
||
|
||
drawPortText = false;
|
||
drawName = false;
|
||
|
||
} else if (sensor.type == "clock") {
|
||
if (!sensor.img || isElementRemoved(sensor.img))
|
||
sensor.img = paper.image(getImg('clock.png'), imgx, imgy, imgw, imgh);
|
||
|
||
sensor.img.attr({
|
||
"x": imgx,
|
||
"y": imgy,
|
||
"width": imgw,
|
||
"height": imgh,
|
||
});
|
||
|
||
sensor.stateText = paper.text(state1x, state1y, context.currentTime.toString() + "ms");
|
||
|
||
drawPortText = false;
|
||
drawName = false;
|
||
}
|
||
|
||
|
||
sensor.focusrect.mousedown(function () {
|
||
if (infos.customSensors && !context.autoGrading) {
|
||
if (context.removerect) {
|
||
context.removerect.remove();
|
||
}
|
||
|
||
if (!context.runner || !context.runner.isRunning()) {
|
||
context.removerect = paper.text(portx, imgy, "\uf00d"); // fa-times char
|
||
removeRect = context.removerect;
|
||
sensorWithRemoveRect = sensor;
|
||
|
||
context.removerect.attr({
|
||
"font-size": "30" + "px",
|
||
fill: "lightgray",
|
||
"font-family": "Font Awesome 5 Free",
|
||
'text-anchor': 'start',
|
||
"x": portx,
|
||
"y": imgy,
|
||
});
|
||
|
||
context.removerect.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
context.removerect.node.style.fontFamily = '"Font Awesome 5 Free"';
|
||
context.removerect.node.style.fontWeight = "bold";
|
||
|
||
|
||
context.removerect.click(function (element) {
|
||
|
||
window.displayHelper.showPopupMessage(strings.messages.removeConfirmation,
|
||
'blanket',
|
||
strings.messages.remove,
|
||
function () {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
if (infos.quickPiSensors[i] === sensor) {
|
||
sensor.removed = true;
|
||
infos.quickPiSensors.splice(i, 1);
|
||
}
|
||
}
|
||
context.recreateDisplay = true;
|
||
context.resetDisplay();
|
||
},
|
||
strings.messages.keep);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
|
||
|
||
if (sensor.stateText) {
|
||
try {
|
||
var statecolor = "gray";
|
||
if (context.compactLayout)
|
||
statecolor = "black";
|
||
|
||
sensor.stateText.attr({ "font-size": statesize + "px", 'text-anchor': stateanchor, 'font-weight': 'bold', fill: statecolor });
|
||
var b = sensor.stateText._getBBox();
|
||
sensor.stateText.translate(0, b.height/2);
|
||
sensor.stateText.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
} catch (err) {
|
||
}
|
||
}
|
||
|
||
|
||
if (drawPortText) {
|
||
if (sensor.portText)
|
||
sensor.portText.remove();
|
||
|
||
sensor.portText = paper.text(portx, porty, sensor.port);
|
||
sensor.portText.attr({ "font-size": portsize + "px", 'text-anchor': 'start', fill: "gray" });
|
||
sensor.portText.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
var b = sensor.portText._getBBox();
|
||
sensor.portText.translate(0,b.height/2);
|
||
}
|
||
|
||
if (sensor.nameText) {
|
||
sensor.nameText.remove();
|
||
}
|
||
|
||
|
||
if (drawName) {
|
||
if (sensor.name) {
|
||
sensor.nameText = paper.text(namex, namey, sensor.name );
|
||
sensor.nameText.attr({ "font-size": namesize + "px", 'text-anchor': nameanchor, fill: "#7B7B7B" });
|
||
sensor.nameText.node.style = "-moz-user-select: none; -webkit-user-select: none;";
|
||
}
|
||
}
|
||
|
||
|
||
if (!donotmovefocusrect) {
|
||
// This needs to be in front of everything
|
||
sensor.focusrect.toFront();
|
||
}
|
||
|
||
// save the sensor if we are not running
|
||
if (!(context.runner && context.runner.isRunning())) {
|
||
if (_findFirst(sensorDefinitions, function(globalSensor) {
|
||
return globalSensor.name === sensor.type;
|
||
}).isSensor) {
|
||
context.sensorsSaved[sensor.name] = {
|
||
state: Array.isArray(sensor.state) ? sensor.state.slice() : sensor.state,
|
||
screenDrawing: sensor.screenDrawing,
|
||
lastDrawnTime: sensor.lastDrawnTime,
|
||
lastDrawnState: sensor.lastDrawnState,
|
||
callsInTimeSlot: sensor.callsInTimeSlot,
|
||
lastTimeIncrease: sensor.lastTimeIncrease,
|
||
removed: sensor.removed,
|
||
quickStore: sensor.quickStore
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
function _findFirst(array, func) {
|
||
for (var i = 0; i < array.length; i++) {
|
||
if (func(array[i]))
|
||
return array[i];
|
||
}
|
||
return undefined;
|
||
}
|
||
|
||
context.sensorsSaved = {};
|
||
|
||
context.registerQuickPiEvent = function (name, newState, setInSensor = true, allowFail = false) {
|
||
var sensor = findSensorByName(name);
|
||
if (!sensor) {
|
||
context.success = false;
|
||
throw (strings.messages.sensorNotFound.format(name));
|
||
}
|
||
|
||
if (setInSensor) {
|
||
sensor.state = newState;
|
||
drawSensor(sensor);
|
||
}
|
||
|
||
if (context.autoGrading && context.gradingStatesBySensor != undefined) {
|
||
var fail = false;
|
||
var type = "actual";
|
||
|
||
if(!context.actualStatesBySensor[name]) {
|
||
context.actualStatesBySensor[name] = [];
|
||
}
|
||
var actualStates = context.actualStatesBySensor[name];
|
||
|
||
var lastRealState = actualStates.length > 0 ? actualStates[actualStates.length-1] : null;
|
||
if(lastRealState) {
|
||
if(lastRealState.time == context.currentTime) {
|
||
lastRealState.state = newState;
|
||
} else {
|
||
actualStates.push({time: context.currentTime, state: newState});
|
||
}
|
||
} else {
|
||
actualStates.push({time: context.currentTime, state: newState});
|
||
}
|
||
|
||
drawNewStateChangesSensor(name, newState);
|
||
|
||
context.increaseTime(sensor);
|
||
}
|
||
}
|
||
|
||
function drawNewStateChangesSensor(name, newState=null) {
|
||
var sensor = findSensorByName(name);
|
||
if (!sensor) {
|
||
context.success = false;
|
||
throw (strings.messages.sensorNotFound.format(name));
|
||
}
|
||
|
||
var sensorDef = findSensorDefinition(sensor);
|
||
if(sensor.lastDrawnState !== null) {
|
||
// Get all states between the last drawn time and now
|
||
var expectedStates = context.getSensorExpectedState(name, sensor.lastDrawnTime, context.currentTime);
|
||
for(var i = 0; expectedStates && i < expectedStates.length; i++) {
|
||
// Draw the line up to the next expected state
|
||
var expectedState = expectedStates[i];
|
||
var nextTime = i+1 < expectedStates.length ? expectedStates[i+1].time : context.currentTime;
|
||
var type = "actual";
|
||
// Check the previous state
|
||
if(!sensorDef.compareState(sensor.lastDrawnState, expectedState.state)) {
|
||
type = "wrong";
|
||
}
|
||
drawSensorTimeLineState(sensor, sensor.lastDrawnState, sensor.lastDrawnTime, nextTime, type, false, expectedState.state);
|
||
sensor.lastDrawnTime = nextTime;
|
||
}
|
||
}
|
||
|
||
sensor.lastDrawnTime = context.currentTime;
|
||
|
||
if(newState !== null && sensor.lastDrawnState != newState) {
|
||
// Draw the new state change
|
||
if(sensor.lastDrawnState === null) {
|
||
sensor.lastDrawnState = newState;
|
||
}
|
||
|
||
var type = "actual";
|
||
// Check the new state
|
||
var expectedState = context.getSensorExpectedState(name, context.currentTime);
|
||
|
||
if (expectedState !== null && !sensorDef.compareState(expectedState.state, newState))
|
||
{
|
||
type = "wrong";
|
||
}
|
||
drawSensorTimeLineState(sensor, newState, context.currentTime, context.currentTime, type, false, expectedState && expectedState.state);
|
||
sensor.lastDrawnState = newState;
|
||
}
|
||
}
|
||
|
||
function drawNewStateChanges() {
|
||
// Draw all sensors
|
||
if(!context.gradingStatesBySensor) { return; }
|
||
for(var sensorName in context.gradingStatesBySensor) {
|
||
drawNewStateChangesSensor(sensorName);
|
||
}
|
||
}
|
||
|
||
context.increaseTime = function (sensor) {
|
||
if (!sensor.lastTimeIncrease) {
|
||
sensor.lastTimeIncrease = 0;
|
||
}
|
||
|
||
if (sensor.callsInTimeSlot == undefined)
|
||
sensor.callsInTimeSlot = 0;
|
||
|
||
if (sensor.lastTimeIncrease == context.currentTime) {
|
||
sensor.callsInTimeSlot += 1;
|
||
}
|
||
else {
|
||
sensor.lastTimeIncrease = context.currentTime;
|
||
sensor.callsInTimeSlot = 1;
|
||
}
|
||
|
||
if (sensor.callsInTimeSlot > getQuickPiOption('increaseTimeAfterCalls')) {
|
||
context.currentTime += context.tickIncrease;
|
||
|
||
sensor.lastTimeIncrease = context.currentTime;
|
||
sensor.callsInTimeSlot = 0;
|
||
}
|
||
|
||
drawCurrentTime();
|
||
if(context.autoGrading)
|
||
{
|
||
drawNewStateChanges();
|
||
}
|
||
|
||
if(context.runner) {
|
||
// Tell the runner an "action" happened
|
||
context.runner.signalAction();
|
||
}
|
||
}
|
||
|
||
context.increaseTimeBy = function (time) {
|
||
|
||
var iStates = 0;
|
||
|
||
var newTime = context.currentTime + time;
|
||
|
||
if (context.gradingStatesByTime) {
|
||
// Advance until current time, ignore everything in the past.
|
||
while (iStates < context.gradingStatesByTime.length &&
|
||
context.gradingStatesByTime[iStates].time < context.currentTime)
|
||
iStates++;
|
||
|
||
for (; iStates < context.gradingStatesByTime.length; iStates++) {
|
||
var sensorState = context.gradingStatesByTime[iStates];
|
||
|
||
// Until the new time
|
||
if (sensorState.time >= newTime)
|
||
break;
|
||
|
||
// Mark all inputs as hit
|
||
if (sensorState.input) {
|
||
sensorState.hit = true;
|
||
// context.currentTime = sensorState.time;
|
||
context.getSensorState(sensorState.name);
|
||
}
|
||
}
|
||
}
|
||
|
||
if(context.runner) {
|
||
// Tell the runner an "action" happened
|
||
context.runner.signalAction();
|
||
}
|
||
|
||
context.currentTime = newTime;
|
||
|
||
drawCurrentTime();
|
||
if (context.autoGrading) {
|
||
drawNewStateChanges();
|
||
}
|
||
}
|
||
|
||
context.getSensorExpectedState = function (name, targetTime = null, upToTime = null) {
|
||
var state = null;
|
||
if(targetTime === null) {
|
||
targetTime = context.currentTime;
|
||
}
|
||
|
||
if (!context.gradingStatesBySensor)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
var actualname = name;
|
||
var parts = name.split(".");
|
||
if (parts.length == 2) {
|
||
actualname = parts[0];
|
||
}
|
||
|
||
var sensorStates = context.gradingStatesBySensor[actualname];
|
||
|
||
if (!sensorStates)
|
||
return null; // Fail??
|
||
|
||
var lastState;
|
||
var startTime = -1;
|
||
for (var idx = 0; idx < sensorStates.length; idx++) {
|
||
if (startTime >= 0
|
||
&& targetTime >= startTime
|
||
&& targetTime < sensorStates[idx].time) {
|
||
state = lastState;
|
||
break;
|
||
}
|
||
|
||
startTime = sensorStates[idx].time;
|
||
lastState = sensorStates[idx];
|
||
}
|
||
|
||
// This is the end state
|
||
if(state === null && targetTime >= startTime) {
|
||
state = lastState;
|
||
}
|
||
|
||
if(state && upToTime !== null) {
|
||
// If upToTime is given, return an array of states instead
|
||
var states = [state];
|
||
for(var idx2 = idx+1; idx2 < sensorStates.length; idx2++) {
|
||
if(sensorStates[idx2].time < upToTime) {
|
||
states.push(sensorStates[idx2]);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
return states;
|
||
} else {
|
||
return state;
|
||
}
|
||
}
|
||
|
||
|
||
context.getSensorState = function (name) {
|
||
var state = null;
|
||
|
||
var sensor = findSensorByName(name);
|
||
if (!context.display || context.autoGrading) {
|
||
var stateTime = context.getSensorExpectedState(name);
|
||
|
||
if (stateTime != null) {
|
||
stateTime.hit = true;
|
||
state = stateTime.state;
|
||
if(sensor) {
|
||
// Redraw from the beginning of this state
|
||
sensor.lastDrawnTime = Math.min(sensor.lastDrawnTime, stateTime.time);
|
||
}
|
||
}
|
||
else {
|
||
state = 0;
|
||
}
|
||
}
|
||
|
||
if (!sensor) {
|
||
context.success = false;
|
||
throw (strings.messages.sensorNotFound.format(name));
|
||
}
|
||
|
||
if (state == null) {
|
||
state = sensor.state;
|
||
}
|
||
else {
|
||
sensor.state = state;
|
||
drawSensor(sensor);
|
||
}
|
||
|
||
drawNewStateChangesSensor(sensor.name, sensor.state);
|
||
|
||
context.increaseTime(sensor);
|
||
|
||
return state;
|
||
}
|
||
|
||
// This will advance grading time to the next button release for waitForButton
|
||
// will return false if the next event wasn't a button press
|
||
context.advanceToNextRelease = function (sensorType, port) {
|
||
var retval = false;
|
||
var iStates = 0;
|
||
|
||
// Advance until current time, ignore everything in the past.
|
||
while (context.gradingStatesByTime[iStates].time <= context.currentTime)
|
||
iStates++;
|
||
|
||
for (; iStates < context.gradingStatesByTime.length; iStates++) {
|
||
sensorState = context.gradingStatesByTime[iStates];
|
||
|
||
if (sensorState.type == sensorType &&
|
||
sensorState.port == port) {
|
||
|
||
sensorState.hit = true;
|
||
if (!sensorState.state) {
|
||
context.currentTime = sensorState.time;
|
||
retval = true;
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
retval = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return retval;
|
||
};
|
||
|
||
|
||
/***** Functions *****/
|
||
/* Here we define each function of the library.
|
||
Blocks will generally use context.group.blockName as their handler
|
||
function, hence we generally use this name for the functions. */
|
||
context.quickpi.turnLedOn = function (callback) {
|
||
|
||
var sensor = findSensorByType("led");
|
||
|
||
context.registerQuickPiEvent(sensor.name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
}
|
||
else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("turnLedOn()", cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.turnLedOff = function (callback) {
|
||
|
||
var sensor = findSensorByType("led");
|
||
|
||
context.registerQuickPiEvent(sensor.name, false);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("turnLedOff()", cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.turnBuzzerOn = function (callback) {
|
||
|
||
context.registerQuickPiEvent("buzzer1", true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
}
|
||
else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("turnBuzzerOn()", cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.turnBuzzerOff = function (callback) {
|
||
context.registerQuickPiEvent("buzzer1", false);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("turnBuzzerOff()", cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.waitForButton = function (name, callback) {
|
||
// context.registerQuickPiEvent("button", "D22", "wait", false);
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading) {
|
||
|
||
context.advanceToNextRelease("button", sensor.port);
|
||
|
||
context.waitDelay(callback);
|
||
} else if (context.offLineMode) {
|
||
if (sensor) {
|
||
var cb = context.runner.waitCallback(callback);
|
||
sensor.onPressed = function () {
|
||
cb();
|
||
}
|
||
} else {
|
||
context.waitDelay(callback);
|
||
}
|
||
}
|
||
else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("waitForButton(\"" + name + "\")", cb);
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.isButtonPressed = function (arg1, arg2) {
|
||
if(typeof arg2 == "undefined") {
|
||
// no arguments
|
||
var callback = arg1;
|
||
var sensor = findSensorByType("button");
|
||
var name = sensor.name;
|
||
} else {
|
||
var callback = arg2;
|
||
var sensor = findSensorByName(arg1, true);
|
||
var name = arg1;
|
||
}
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
|
||
if (sensor.type == "stick") {
|
||
var state = context.getSensorState(name);
|
||
var stickDefinition = findSensorDefinition(sensor);
|
||
var buttonstate = stickDefinition.getButtonState(name, sensor.state);
|
||
|
||
|
||
context.runner.noDelay(callback, buttonstate);
|
||
} else {
|
||
var state = context.getSensorState(name);
|
||
|
||
context.runner.noDelay(callback, state);
|
||
}
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
if (sensor.type == "stick") {
|
||
var stickDefinition = findSensorDefinition(sensor);
|
||
|
||
stickDefinition.getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
|
||
var buttonstate = stickDefinition.getButtonState(name, sensor.state);
|
||
|
||
cb(buttonstate);
|
||
});
|
||
|
||
} else {
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal != "0";
|
||
drawSensor(sensor);
|
||
cb(returnVal != "0");
|
||
});
|
||
}
|
||
}
|
||
};
|
||
|
||
context.quickpi.isButtonPressedWithName = context.quickpi.isButtonPressed;
|
||
|
||
context.quickpi.buttonWasPressed = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var state = context.getSensorState(name);
|
||
|
||
var wasPressed = !!sensor.wasPressed;
|
||
sensor.wasPressed = false;
|
||
|
||
context.runner.noDelay(callback, wasPressed);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
context.quickPiConnection.sendCommand("buttonWasPressed(\"" + name + "\")", function (returnVal) {
|
||
cb(returnVal != "0");
|
||
});
|
||
}
|
||
|
||
};
|
||
|
||
context.quickpi.setLedState = function (name, state, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
var command = "setLedState(\"" + sensor.port + "\"," + (state ? "True" : "False") + ")";
|
||
|
||
context.registerQuickPiEvent(name, state ? true : false);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.setBuzzerState = function (name, state, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
var command = "setBuzzerState(\"" + name + "\"," + (state ? "True" : "False") + ")";
|
||
|
||
context.registerQuickPiEvent(name, state ? true : false);
|
||
|
||
if(context.display) {
|
||
state ? buzzerSound.start(name) : buzzerSound.stop(name);
|
||
}
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.isBuzzerOn = function (arg1, arg2) {
|
||
if(typeof arg2 == "undefined") {
|
||
// no arguments
|
||
var callback = arg1;
|
||
var sensor = findSensorByType("buzzer");
|
||
} else {
|
||
var callback = arg2;
|
||
var sensor = findSensorByName(arg1, true);
|
||
}
|
||
|
||
var command = "isBuzzerOn(\"" + sensor.name + "\")";
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var state = context.getSensorState("buzzer1");
|
||
context.waitDelay(callback, state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) {
|
||
returnVal = parseFloat(returnVal)
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.isBuzzerOnWithName = context.quickpi.isBuzzerOn;
|
||
|
||
context.quickpi.setBuzzerNote = function (name, frequency, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
var command = "setBuzzerNote(\"" + name + "\"," + frequency + ")";
|
||
|
||
context.registerQuickPiEvent(name, frequency);
|
||
|
||
if(context.display && context.offLineMode) {
|
||
buzzerSound.start(name, frequency);
|
||
}
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) {
|
||
returnVal = parseFloat(returnVal)
|
||
cb(returnVal);
|
||
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.getBuzzerNote = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
var command = "getBuzzerNote(\"" + name + "\")";
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback, sensor.state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) {
|
||
returnVal = parseFloat(returnVal)
|
||
cb(returnVal);
|
||
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.setLedBrightness = function (name, level, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (typeof level == "object")
|
||
{
|
||
level = level.valueOf();
|
||
}
|
||
|
||
var command = "setLedBrightness(\"" + name + "\"," + level + ")";
|
||
|
||
context.registerQuickPiEvent(name, level);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, cb);
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.getLedBrightness = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
var command = "getLedBrightness(\"" + name + "\")";
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback, sensor.state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) {
|
||
returnVal = parseFloat(returnVal)
|
||
cb(returnVal);
|
||
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.isLedOn = function (arg1, arg2) {
|
||
if(typeof arg2 == "undefined") {
|
||
// no arguments
|
||
var callback = arg1;
|
||
var sensor = findSensorByType("led");
|
||
} else {
|
||
var callback = arg2;
|
||
var sensor = findSensorByName(arg1, true);
|
||
}
|
||
|
||
var command = "getLedState(\"" + sensor.name + "\")";
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback, sensor.state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) {
|
||
returnVal = parseFloat(returnVal)
|
||
cb(returnVal);
|
||
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.isLedOnWithName = context.quickpi.isLedOn;
|
||
|
||
|
||
context.quickpi.toggleLedState = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
var command = "toggleLedState(\"" + name + "\")";
|
||
var state = sensor.state;
|
||
|
||
context.registerQuickPiEvent(name, !state);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) { return returnVal != "0"; });
|
||
}
|
||
};
|
||
|
||
context.quickpi.displayText = function (line1, arg2, arg3) {
|
||
if(typeof arg3 == "undefined") {
|
||
// Only one argument
|
||
var line2 = null;
|
||
var callback = arg2;
|
||
} else {
|
||
var line2 = arg2;
|
||
var callback = arg3;
|
||
}
|
||
|
||
var sensor = findSensorByType("screen");
|
||
|
||
var command = "displayText(\"" + line1 + "\", \"\")";
|
||
|
||
context.registerQuickPiEvent(sensor.name,
|
||
{
|
||
line1: line1,
|
||
line2: line2
|
||
}
|
||
);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function (retval) {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.displayText2Lines = context.quickpi.displayText;
|
||
|
||
context.quickpi.readTemperature = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var state = context.getSensorState(name);
|
||
|
||
context.runner.waitDelay(callback, state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.sleep = function (time, callback) {
|
||
context.increaseTimeBy(time);
|
||
if (!context.display || context.autoGrading) {
|
||
context.runner.noDelay(callback);
|
||
}
|
||
else {
|
||
context.runner.waitDelay(callback, null, time);
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.setServoAngle = function (name, angle, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (angle > 180)
|
||
angle = 180;
|
||
else if (angle < 0)
|
||
angle = 0;
|
||
|
||
context.registerQuickPiEvent(name, angle);
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var command = "setServoAngle(\"" + name + "\"," + angle + ")";
|
||
cb = context.runner.waitCallback(callback);
|
||
context.quickPiConnection.sendCommand(command, cb);
|
||
}
|
||
};
|
||
|
||
context.quickpi.getServoAngle = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
var command = "getServoAngle(\"" + name + "\")";
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback, sensor.state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand(command, function(returnVal) {
|
||
returnVal = parseFloat(returnVal);
|
||
cb(returnVal);
|
||
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.readRotaryAngle = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
|
||
var state = context.getSensorState(name);
|
||
context.waitDelay(callback, state);
|
||
} else {
|
||
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.readDistance = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
|
||
var state = context.getSensorState(name);
|
||
context.waitDelay(callback, state);
|
||
} else {
|
||
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
|
||
context.quickpi.readLightIntensity = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
|
||
var state = context.getSensorState(name);
|
||
context.waitDelay(callback, state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.readHumidity = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
|
||
var state = context.getSensorState(name);
|
||
context.waitDelay(callback, state);
|
||
} else {
|
||
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.currentTime = function (callback) {
|
||
var millis = new Date().getTime();
|
||
|
||
if (context.autoGrading) {
|
||
millis = context.currentTime;
|
||
}
|
||
|
||
context.runner.waitDelay(callback, millis);
|
||
};
|
||
|
||
|
||
var getTemperatureFromCloudURl = "https://cloud.quick-pi.org/cache/weather.php";
|
||
|
||
var getTemperatureFromCloudSupportedTowns = [];
|
||
|
||
// setup the supported towns
|
||
$.get(getTemperatureFromCloudURl + "?q=" + "supportedtowns", function(towns) {
|
||
getTemperatureFromCloudSupportedTowns = JSON.parse(towns);
|
||
});
|
||
|
||
// We create a cache so there is less calls to the api and we get the results of the temperature faster
|
||
var getTemperatureFromCloudCache = {};
|
||
|
||
context.quickpi.getTemperatureFromCloud = function(location, callback) {
|
||
var url = getTemperatureFromCloudURl;
|
||
|
||
if (!arrayContains(getTemperatureFromCloudSupportedTowns, location))
|
||
throw strings.messages.getTemperatureFromCloudWrongValue.format(location);
|
||
|
||
var cache = getTemperatureFromCloudCache;
|
||
if (cache[location] != undefined && ((Date.now() - cache[location].lastUpdate) / 1000) / 60 < 10) {
|
||
context.waitDelay(callback, cache[location].temperature);
|
||
return;
|
||
}
|
||
|
||
var cb = context.runner.waitCallback(callback);
|
||
$.get(url + "?q=" + location, function(data) {
|
||
// If the server return invalid it mean that the town given is not supported
|
||
if (data === "invalid") {
|
||
// This only happen when the user give an invalid town to the server, which should never happen because
|
||
// the validity of the user input is checked above.
|
||
cb(0);
|
||
} else {
|
||
cache[location] = {
|
||
lastUpdate: Date.now(),
|
||
temperature: data
|
||
};
|
||
cb(data);
|
||
}
|
||
});
|
||
};
|
||
|
||
context.initScreenDrawing = function(sensor) {
|
||
if (!sensor.screenDrawing)
|
||
sensor.screenDrawing = new screenDrawing(sensor.canvas);
|
||
}
|
||
|
||
|
||
context.quickpi.drawPoint = function(x, y, callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.drawPoint(x, y);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "drawPoint(" + x + "," + y + ")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.isPointSet = function(x, y, callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
var value = sensor.screenDrawing.isPointSet(x, y);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback, value);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "isPointSet(" + x + "," + y + ")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.drawLine = function(x0, y0, x1, y1, callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.drawLine(x0, y0, x1, y1);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "drawLine(" + x0 + "," + y0 + "," + x1 + "," + y1 + ")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.drawRectangle = function(x0, y0, width, height, callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.drawRectangle(x0, y0, width, height);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "drawRectangle(" + x0 + "," + y0 + "," + width + "," + height + ")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.drawCircle = function(x0, y0, diameter, callback) {
|
||
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.drawCircle(x0, y0, diameter, diameter);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "drawCircle(" + x0 + "," + y0 + "," + diameter + ")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.clearScreen = function(callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.clearScreen();
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "clearScreen()";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.updateScreen = function(callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "updateScreen()";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.autoUpdate = function(autoupdate, callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "autoUpdate(\"" + (autoupdate ? "True" : "False") + "\")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.fill = function(color, callback) {
|
||
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.fill(color);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "fill(\"" + color + "\")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.noFill = function(callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.noFill();
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "NoFill()";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.stroke = function(color, callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.stroke(color);
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
var command = "stroke(\"" + color + "\")";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.noStroke = function(callback) {
|
||
var sensor = findSensorByType("screen");
|
||
|
||
context.initScreenDrawing(sensor);
|
||
sensor.screenDrawing.noStroke();
|
||
context.registerQuickPiEvent(sensor.name, sensor.screenDrawing.getStateData());
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "noStroke()";
|
||
context.quickPiConnection.sendCommand(command, function () {
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.readAcceleration = function(axis, callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("accelerometer");
|
||
|
||
var index = 0;
|
||
if (axis == "x")
|
||
index = 0;
|
||
else if (axis == "y")
|
||
index = 1;
|
||
else if (axis == "z")
|
||
index = 2;
|
||
|
||
var state = context.getSensorState(sensor.name);
|
||
|
||
if (Array.isArray(state))
|
||
context.waitDelay(callback, state[index]);
|
||
else
|
||
context.waitDelay(callback, 0);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
var command = "readAcceleration(\"" + axis + "\")";
|
||
context.quickPiConnection.sendCommand(command, function (returnVal) {
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.computeRotation = function(rotationType, callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("accelerometer");
|
||
|
||
var zsign = 1;
|
||
var result = 0;
|
||
|
||
if (sensor.state[2] < 0)
|
||
zsign = -1;
|
||
|
||
if (rotationType == "pitch")
|
||
{
|
||
result = 180 * Math.atan2 (sensor.state[0], zsign * Math.sqrt(sensor.state[1]*sensor.state[1] + sensor.state[2]*sensor.state[2]))/Math.PI;
|
||
}
|
||
else if (rotationType == "roll")
|
||
{
|
||
result = 180 * Math.atan2 (sensor.state[1], zsign * Math.sqrt(sensor.state[0]*sensor.state[0] + sensor.state[2]*sensor.state[2]))/Math.PI;
|
||
}
|
||
|
||
result = Math.round(result);
|
||
|
||
context.waitDelay(callback, result);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
var command = "computeRotation(\"" + rotationType + "\")";
|
||
|
||
context.quickPiConnection.sendCommand(command, function (returnVal) {
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.readSoundLevel = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var state = context.getSensorState(name);
|
||
|
||
context.runner.noDelay(callback, state);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.readMagneticForce = function (axis, callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("magnetometer");
|
||
|
||
var index = 0;
|
||
if (axis == "x")
|
||
index = 0;
|
||
else if (axis == "y")
|
||
index = 1;
|
||
else if (axis == "z")
|
||
index = 2;
|
||
|
||
context.waitDelay(callback, sensor.state[index]);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
var sensor = context.findSensor("magnetometer", "i2c");
|
||
|
||
findSensorDefinition(sensor).getLiveState(axis, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
|
||
if (axis == "x")
|
||
returnVal = returnVal[0];
|
||
else if (axis == "y")
|
||
returnVal = returnVal[1];
|
||
else if (axis == "z")
|
||
returnVal = returnVal[2];
|
||
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.computeCompassHeading = function (callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("magnetometer");
|
||
|
||
var heading = Math.atan2(sensor.state[0],sensor.state[1])*(180/Math.PI) + 180;
|
||
|
||
heading = Math.round(heading);
|
||
|
||
context.runner.noDelay(callback, heading);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
var sensor = context.findSensor("magnetometer", "i2c");
|
||
|
||
context.quickPiConnection.sendCommand("readMagnetometerLSM303C()", function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
|
||
returnVal = Math.atan2(sensor.state[0],sensor.state[1])*(180/Math.PI) + 180;
|
||
|
||
returnVal = Math.floor(returnVal);
|
||
|
||
cb(returnVal);
|
||
}, true);
|
||
}
|
||
};
|
||
|
||
context.quickpi.readInfraredState = function (name, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var state = context.getSensorState(name);
|
||
|
||
context.runner.noDelay(callback, state ? true : false);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).getLiveState(sensor, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.setInfraredState = function (name, state, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
context.registerQuickPiEvent(name, state ? true : false);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
findSensorDefinition(sensor).setLiveState(sensor, state, cb);
|
||
}
|
||
};
|
||
|
||
|
||
//// Gyroscope
|
||
context.quickpi.readAngularVelocity = function (axis, callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("gyroscope");
|
||
|
||
var index = 0;
|
||
if (axis == "x")
|
||
index = 0;
|
||
else if (axis == "y")
|
||
index = 1;
|
||
else if (axis == "z")
|
||
index = 2;
|
||
|
||
context.waitDelay(callback, sensor.state[index]);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
var sensor = context.findSensor("gyroscope", "i2c");
|
||
|
||
findSensorDefinition(sensor).getLiveState(axis, function(returnVal) {
|
||
sensor.state = returnVal;
|
||
drawSensor(sensor);
|
||
|
||
if (axis == "x")
|
||
returnVal = returnVal[0];
|
||
else if (axis == "y")
|
||
returnVal = returnVal[1];
|
||
else if (axis == "z")
|
||
returnVal = returnVal[2];
|
||
|
||
cb(returnVal);
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.setGyroZeroAngle = function (callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("gyroscope");
|
||
|
||
sensor.rotationAngles = [0, 0, 0];
|
||
sensor.lastSpeedChange = new Date();
|
||
|
||
context.runner.noDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("setGyroZeroAngle()", function(returnVal) {
|
||
cb();
|
||
}, true);
|
||
}
|
||
};
|
||
|
||
context.quickpi.computeRotationGyro = function (axis, callback) {
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var sensor = findSensorByType("gyroscope");
|
||
|
||
|
||
var ret = 0;
|
||
|
||
if (sensor.rotationAngles != undefined) {
|
||
for (var i = 0; i < 3; i++)
|
||
sensor.rotationAngles[i] += sensor.state[i] * ((new Date() - sensor.lastSpeedChange) / 1000);
|
||
|
||
sensor.lastSpeedChange = new Date();
|
||
|
||
if (axis == "x")
|
||
ret = sensor.rotationAngles[0];
|
||
else if (axis == "y")
|
||
ret = sensor.rotationAngles[1];
|
||
else if (axis == "z")
|
||
ret = sensor.rotationAngles[2];
|
||
}
|
||
|
||
context.runner.noDelay(callback, ret);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
var sensor = context.findSensor("gyroscope", "i2c");
|
||
|
||
context.quickPiConnection.sendCommand("computeRotationGyro()", function(returnVal) {
|
||
//sensor.state = returnVal;
|
||
//drawSensor(sensor);
|
||
|
||
var returnVal = JSON.parse(returnVal);
|
||
|
||
if (axis == "x")
|
||
returnVal = returnVal[0];
|
||
else if (axis == "y")
|
||
returnVal = returnVal[1];
|
||
else if (axis == "z")
|
||
returnVal = returnVal[2];
|
||
|
||
cb(returnVal);
|
||
}, true);
|
||
}
|
||
};
|
||
|
||
|
||
context.quickpi.connectToCloudStore = function (prefix, password, callback) {
|
||
var sensor = findSensorByType("cloudstore");
|
||
|
||
if (!context.display || context.autoGrading) {
|
||
sensor.quickStore = new quickPiStore(true);
|
||
} else {
|
||
sensor.quickStore = QuickStore(prefix, password);
|
||
}
|
||
|
||
context.runner.noDelay(callback, 0);
|
||
};
|
||
|
||
context.quickpi.writeToCloudStore = function (identifier, key, value, callback) {
|
||
var sensor = findSensorByType("cloudstore");
|
||
|
||
if (!sensor.quickStore || !sensor.quickStore.connected)
|
||
{
|
||
context.success = false;
|
||
throw("Cloud store not connected");
|
||
}
|
||
|
||
if (!context.display || context.autoGrading) {
|
||
sensor.quickStore.write(identifier, key, value);
|
||
|
||
context.registerQuickPiEvent(sensor.name, sensor.quickStore.getStateData());
|
||
|
||
context.runner.noDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
sensor.quickStore.write(identifier, key, value, function(data) {
|
||
if (!data || !data.success)
|
||
{
|
||
if (data && data.message)
|
||
context.failImmediately = "cloudstore: " + data.message;
|
||
else
|
||
context.failImmediately = "Error trying to communicate with cloud store";
|
||
|
||
}
|
||
cb();
|
||
});
|
||
}
|
||
};
|
||
|
||
context.quickpi.readFromCloudStore = function (identifier, key, callback) {
|
||
var sensor = findSensorByType("cloudstore");
|
||
|
||
if (!sensor.quickStore)
|
||
{
|
||
if (!context.display || context.autoGrading) {
|
||
sensor.quickStore = new quickPiStore();
|
||
} else {
|
||
sensor.quickStore = QuickStore();
|
||
}
|
||
}
|
||
|
||
if (!context.display || context.autoGrading) {
|
||
var state = context.getSensorState(sensor.name);
|
||
var value = "";
|
||
|
||
if (state.hasOwnProperty(key)) {
|
||
value = state[key];
|
||
}
|
||
else {
|
||
context.success = false;
|
||
throw("Key not found");
|
||
}
|
||
|
||
sensor.quickStore.write(identifier, key, value);
|
||
context.registerQuickPiEvent(sensor.name, sensor.quickStore.getStateData());
|
||
|
||
context.runner.noDelay(callback, value);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
sensor.quickStore.read(identifier, key, function(data) {
|
||
var value = "";
|
||
if (data && data.success)
|
||
{
|
||
try {
|
||
value = JSON.parse(data.value);
|
||
} catch(err)
|
||
{
|
||
value = data.value;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (data && data.message)
|
||
context.failImmediately = "cloudstore: " + data.message;
|
||
else
|
||
context.failImmediately = "Error trying to communicate with cloud store";
|
||
}
|
||
|
||
cb(value);
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
|
||
|
||
context.quickpi.readIRMessage = function (name, timeout, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
var state = context.getSensorState(name);
|
||
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
sensor.waitingForIrMessage = function(command)
|
||
{
|
||
clearTimeout(sensor.waitingForIrMessageTimeout);
|
||
sensor.waitingForIrMessage = null;
|
||
|
||
cb(command);
|
||
}
|
||
|
||
sensor.waitingForIrMessageTimeout = setTimeout(function () {
|
||
if (sensor.waitingForIrMessage) {
|
||
sensor.waitingForIrMessage = null;
|
||
cb("none");
|
||
}
|
||
},
|
||
timeout);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("readIRMessage(\"irrec1\", " + timeout + ")", function(returnVal) {
|
||
|
||
if (typeof returnVal === 'string')
|
||
returnVal = returnVal.replace(/['"]+/g, '')
|
||
|
||
cb(returnVal);
|
||
}, true);
|
||
}
|
||
};
|
||
|
||
context.quickpi.sendIRMessage = function (name, preset, callback) {
|
||
var sensor = findSensorByName(name, true);
|
||
|
||
//context.registerQuickPiEvent(name, state ? true : false);
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("sendIRMessage(\"irtran1\", \"" + preset + "\")", function(returnVal) {
|
||
cb();
|
||
}, true);
|
||
}
|
||
};
|
||
|
||
context.quickpi.presetIRMessage = function (preset, data, callback) {
|
||
//var sensor = findSensorByName(name, true);
|
||
|
||
//context.registerQuickPiEvent(name, state ? true : false);
|
||
if (!context.remoteIRcodes)
|
||
|
||
context.remoteIRcodes = {};
|
||
|
||
context.remoteIRcodes[preset] = data;
|
||
|
||
if (!context.display || context.autoGrading || context.offLineMode) {
|
||
context.waitDelay(callback);
|
||
} else {
|
||
var cb = context.runner.waitCallback(callback);
|
||
|
||
context.quickPiConnection.sendCommand("presetIRMessage(\"" + preset + "\", \"" + JSON.stringify(JSON.parse(data)) + "\")", function(returnVal) {
|
||
cb();
|
||
}, true);
|
||
}
|
||
};
|
||
/***** Blocks definitions *****/
|
||
/* Here we define all blocks/functions of the library.
|
||
Structure is as follows:
|
||
{
|
||
group: [{
|
||
name: "someName",
|
||
// category: "categoryName",
|
||
// yieldsValue: optional true: Makes a block with return value rather than simple command
|
||
// params: optional array of parameter types. The value 'null' denotes /any/ type. For specific types, see the Blockly documentation ([1,2])
|
||
// handler: optional handler function. Otherwise the function context.group.blockName will be used
|
||
// blocklyJson: optional Blockly JSON objects
|
||
// blocklyInit: optional function for Blockly.Blocks[name].init
|
||
// if not defined, it will be defined to call 'this.jsonInit(blocklyJson);
|
||
// blocklyXml: optional Blockly xml string
|
||
// codeGenerators: optional object:
|
||
// { Python: function that generates Python code
|
||
// JavaScript: function that generates JS code
|
||
// }
|
||
}]
|
||
}
|
||
[1] https://developers.google.com/blockly/guides/create-custom-blocks/define-blocks
|
||
[2] https://developers.google.com/blockly/guides/create-custom-blocks/type-checks
|
||
*/
|
||
|
||
|
||
function getSensorNames(sensorType)
|
||
{
|
||
return function () {
|
||
var ports = [];
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
if (sensor.type == sensorType) {
|
||
ports.push([sensor.name, sensor.name]);
|
||
}
|
||
}
|
||
|
||
if (sensorType == "button") {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
if (sensor.type == "stick") {
|
||
var stickDefinition = findSensorDefinition(sensor);
|
||
|
||
for (var iStick = 0; iStick < stickDefinition.gpiosNames.length; iStick++) {
|
||
var name = sensor.name + "." + stickDefinition.gpiosNames[iStick];
|
||
|
||
ports.push([name, name]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ports.length == 0) {
|
||
ports.push(["none", "none"]);
|
||
}
|
||
|
||
return ports;
|
||
}
|
||
}
|
||
|
||
|
||
function findSensorByName(name, error=false) {
|
||
|
||
if (isNaN(name.substring(0, 1)) && !isNaN(name.substring(1))) {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
if (sensor.port.toUpperCase() == name.toUpperCase()) {
|
||
return sensor;
|
||
}
|
||
}
|
||
} else {
|
||
var firstname = name.split(".")[0];
|
||
|
||
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
|
||
if (sensor.name.toUpperCase() == firstname.toUpperCase()) {
|
||
return sensor;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (error) {
|
||
context.success = false;
|
||
throw (strings.messages.sensorNotFound.format(name));
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function findSensorByType(type) {
|
||
var firstname = name.split(".")[0];
|
||
|
||
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
if (sensor.type == type) {
|
||
return sensor;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function findSensorByPort(port) {
|
||
for (var i = 0; i < infos.quickPiSensors.length; i++) {
|
||
var sensor = infos.quickPiSensors[i];
|
||
if (sensor.port == port) {
|
||
return sensor;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function getSensorSuggestedName(type, suggested) {
|
||
if (suggested) {
|
||
if (!findSensorByName(suggested))
|
||
return suggested;
|
||
}
|
||
|
||
var i = 0;
|
||
var newName;
|
||
|
||
do {
|
||
i++;
|
||
newName = type + i.toString();
|
||
} while (findSensorByName(newName));
|
||
|
||
return newName;
|
||
}
|
||
|
||
|
||
context.customBlocks = {
|
||
// Define our blocks for our namespace "template"
|
||
quickpi: {
|
||
// Categories are reflected in the Blockly menu
|
||
sensors: [
|
||
{ name: "currentTime", yieldsValue: true },
|
||
|
||
{
|
||
name: "waitForButton", params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("button")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "isButtonPressed", yieldsValue: true
|
||
},
|
||
{
|
||
name: "isButtonPressedWithName", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("button")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "buttonWasPressed", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("button")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readTemperature", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("temperature")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readRotaryAngle", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("potentiometer")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readDistance", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("range")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readLightIntensity", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("light")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readHumidity", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("humidity")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readAcceleration", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": [["x", "x"], ["y", "y"], ["z", "z"] ]
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "computeRotation", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": [["pitch", "pitch"], ["roll", "roll"]]
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readSoundLevel", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("sound")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readMagneticForce", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": [["x", "x"], ["y", "y"], ["z", "z"] ]
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "computeCompassHeading", yieldsValue: true
|
||
},
|
||
{
|
||
name: "readInfraredState", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("irrecv")
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "readIRMessage", yieldsValue: true, params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("irrecv") },
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='readIRMessage'>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'><field name='NUM'>10000</field></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "readAngularVelocity", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": [["x", "x"], ["y", "y"], ["z", "z"] ]
|
||
}
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "setGyroZeroAngle"
|
||
},
|
||
{
|
||
name: "computeRotationGyro", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": [["x", "x"], ["y", "y"], ["z", "z"] ]
|
||
}
|
||
]
|
||
}
|
||
},
|
||
|
||
],
|
||
actuator: [
|
||
{ name: "turnLedOn" },
|
||
{ name: "turnLedOff" },
|
||
{ name: "turnBuzzerOn" },
|
||
{ name: "turnBuzzerOff" },
|
||
{
|
||
name: "setLedState", params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("led")
|
||
},
|
||
{ "type": "field_dropdown", "name": "PARAM_1", "options": [[strings.messages.on.toUpperCase(), "1"], [strings.messages.off.toUpperCase(), "0"]] },
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "setBuzzerState", params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("buzzer")
|
||
},
|
||
{ "type": "field_dropdown", "name": "PARAM_1", "options": [[strings.messages.on.toUpperCase(), "1"], [strings.messages.off.toUpperCase(), "0"]] },
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "setBuzzerNote", params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("buzzer")
|
||
},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='setBuzzerNote'>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'><field name='NUM'>200</field></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "getBuzzerNote", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("buzzer")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "setLedBrightness", params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("led")
|
||
},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='setLedBrightness'>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "getLedBrightness", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("led")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "isLedOn", yieldsValue: true
|
||
},
|
||
{
|
||
name: "isLedOnWithName", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("led")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "isBuzzerOn", yieldsValue: true
|
||
},
|
||
{
|
||
name: "isBuzzerOnWithName", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("buzzer")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "toggleLedState", params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("led")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "setServoAngle", params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("servo")
|
||
},
|
||
{ "type": "input_value", "name": "PARAM_1" },
|
||
|
||
]
|
||
},
|
||
blocklyXml: "<block type='setServoAngle'>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "getServoAngle", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{
|
||
"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("servo")
|
||
},
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "setInfraredState", params: ["String", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("irtrans")},
|
||
{ "type": "field_dropdown", "name": "PARAM_1", "options": [[strings.messages.on.toUpperCase(), "1"], [strings.messages.off.toUpperCase(), "0"]] },
|
||
]
|
||
}
|
||
},
|
||
{
|
||
name: "sendIRMessage", params: ["String", "String"], blocklyJson: {
|
||
"args0": [
|
||
{"type": "field_dropdown", "name": "PARAM_0", "options": getSensorNames("irtrans")},
|
||
{ "type": "input_value", "name": "PARAM_1", "text": "" },
|
||
]
|
||
},
|
||
blocklyXml: "<block type='sendIRMessage'>" +
|
||
"<value name='PARAM_1'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "presetIRMessage", params: ["String", "String"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", "text": "" },
|
||
{ "type": "input_value", "name": "PARAM_1", "text": "" },
|
||
]
|
||
},
|
||
blocklyXml: "<block type='presetIRMessage'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "sleep", params: ["Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", "value": 0 },
|
||
]
|
||
}
|
||
,
|
||
blocklyXml: "<block type='sleep'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'><field name='NUM'>1000</field></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
],
|
||
display: [
|
||
{
|
||
name: "displayText", params: ["String", "String"], variants: [[null], [null, null]], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", "text": "" },
|
||
]
|
||
},
|
||
blocklyXml: "<block type='displayText'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'>" + strings.messages.hello + "</field> </shadow></value>" +
|
||
"</block>"
|
||
|
||
},
|
||
{
|
||
name: "displayText2Lines", params: ["String", "String"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", "text": "" },
|
||
{ "type": "input_value", "name": "PARAM_1", "text": "" },
|
||
]
|
||
},
|
||
blocklyXml: "<block type='displayText2Lines'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'>" + strings.messages.hello + "</field> </shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
|
||
},
|
||
{
|
||
name: "drawPoint", params: ["Number", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='drawPoint'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "isPointSet", yieldsValue: true, params: ["Number", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='isPointSet'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "drawLine", params: ["Number", "Number", "Number", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
{ "type": "input_value", "name": "PARAM_2"},
|
||
{ "type": "input_value", "name": "PARAM_3"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='drawLine'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_2'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_3'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "drawRectangle", params: ["Number", "Number", "Number", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
{ "type": "input_value", "name": "PARAM_2"},
|
||
{ "type": "input_value", "name": "PARAM_3"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='drawRectangle'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_2'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_3'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "drawCircle", params: ["Number", "Number", "Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
{ "type": "input_value", "name": "PARAM_1"},
|
||
{ "type": "input_value", "name": "PARAM_2"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='drawCircle'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='math_number'></shadow></value>" +
|
||
"<value name='PARAM_2'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
|
||
{
|
||
name: "clearScreen"
|
||
},
|
||
{
|
||
name: "updateScreen"
|
||
},
|
||
{
|
||
name: "autoUpdate", params: ["Boolean"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
],
|
||
},
|
||
blocklyXml: "<block type='autoUpdate'>" +
|
||
"<value name='PARAM_0'><shadow type='logic_boolean'></shadow></value>" +
|
||
"</block>"
|
||
|
||
},
|
||
{
|
||
name: "fill", params: ["Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='fill'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "noFill"
|
||
},
|
||
{
|
||
name: "stroke", params: ["Number"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='stroke'>" +
|
||
"<value name='PARAM_0'><shadow type='math_number'></shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "noStroke"
|
||
},
|
||
],
|
||
internet: [
|
||
{
|
||
name: "getTemperatureFromCloud", yieldsValue: true, params: ["String"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "field_input", "name": "PARAM_0", text: "Paris"},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='getTemperatureFromCloud'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "connectToCloudStore", params: ["String", "String"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", text: ""},
|
||
{ "type": "input_value", "name": "PARAM_1", text: ""},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='connectToCloudStore'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "writeToCloudStore", params: ["String", "String", "String"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", text: ""},
|
||
{ "type": "input_value", "name": "PARAM_1", text: ""},
|
||
{ "type": "input_value", "name": "PARAM_2", text: ""},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='writeToCloudStore'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"<value name='PARAM_2'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
},
|
||
{
|
||
name: "readFromCloudStore", yieldsValue: true, params: ["String", "String"], blocklyJson: {
|
||
"args0": [
|
||
{ "type": "input_value", "name": "PARAM_0", text: ""},
|
||
{ "type": "input_value", "name": "PARAM_1", text: ""},
|
||
]
|
||
},
|
||
blocklyXml: "<block type='readFromCloudStore'>" +
|
||
"<value name='PARAM_0'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"<value name='PARAM_1'><shadow type='text'><field name='TEXT'></field> </shadow></value>" +
|
||
"</block>"
|
||
},
|
||
|
||
]
|
||
}
|
||
// We can add multiple namespaces by adding other keys to customBlocks.
|
||
};
|
||
|
||
// Color indexes of block categories (as a hue in the range 0–420)
|
||
context.provideBlocklyColours = function () {
|
||
return {
|
||
categories: {
|
||
actuator: 0,
|
||
sensors: 100,
|
||
internet: 200,
|
||
display: 300,
|
||
}
|
||
};
|
||
};
|
||
|
||
// Constants available in Python
|
||
context.customConstants = {
|
||
quickpi: [
|
||
]
|
||
};
|
||
|
||
// Don't forget to return our newly created context!
|
||
return context;
|
||
}
|
||
|
||
// Register the library; change "template" by the name of your library in lowercase
|
||
if (window.quickAlgoLibraries) {
|
||
quickAlgoLibraries.register('quickpi', getContext);
|
||
} else {
|
||
if (!window.quickAlgoLibrariesList) { window.quickAlgoLibrariesList = []; }
|
||
window.quickAlgoLibrariesList.push(['quickpi', getContext]);
|
||
}
|
||
|
||
var sensorWithSlider = null;
|
||
var removeRect = null;
|
||
var sensorWithRemoveRect = null;
|
||
|
||
window.addEventListener('click', function (e) {
|
||
var keep = false;
|
||
var keepremove = false;
|
||
e = e || window.event;
|
||
var target = e.target || e.srcElement;
|
||
|
||
if (sensorWithRemoveRect && sensorWithRemoveRect.focusrect && target == sensorWithRemoveRect.focusrect.node)
|
||
keepremove = true;
|
||
|
||
if (removeRect && !keepremove) {
|
||
removeRect.remove();
|
||
removeRect = null;
|
||
}
|
||
|
||
if (sensorWithSlider && sensorWithSlider.focusrect && target == sensorWithSlider.focusrect.node)
|
||
keep = true;
|
||
|
||
if (sensorWithSlider && sensorWithSlider.sliders) {
|
||
for (var i = 0; i < sensorWithSlider.sliders.length; i++) {
|
||
sensorWithSlider.sliders[i].slider.forEach(function (element) {
|
||
if (target == element.node ||
|
||
target.parentNode == element.node) {
|
||
keep = true;
|
||
return false;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
if (!keep) {
|
||
hideSlider(sensorWithSlider);
|
||
}
|
||
|
||
}, false);//<-- we'll get to the false in a minute
|
||
|
||
|
||
function hideSlider(sensor) {
|
||
if (!sensor)
|
||
return;
|
||
|
||
if (sensor.sliders) {
|
||
for (var i = 0; i < sensor.sliders.length; i++) {
|
||
sensor.sliders[i].slider.remove();
|
||
}
|
||
sensor.sliders = [];
|
||
}
|
||
|
||
|
||
if (sensor.focusrect && sensor.focusrect.paper && sensor.focusrect.paper.canvas)
|
||
sensor.focusrect.toFront();
|
||
};
|