<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>View/Create/Delete Particle Access Tokens</title>
<!-- Bootstrap -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<!-- Styles -->
<link href="style.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- login modal -->
<div id="login-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="loginModal" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Particle login</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger" role="alert">
<p>Check your login details.</p>
</div>
<form id="particle-login">
<div class="form-group">
<label class="sr-only" for="emailAddress">Email address</label>
<input name="username" type="email" class="form-control" id="emailAddress" placeholder="Email address">
</div>
<div class="form-group">
<label class="sr-only" for="password">Password</label>
<input name="password" password="password" type="password" class="form-control" id="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary btn-block">Log in</button>
</form>
</div>
</div>
</div>
</div>
<!-- devices modal -->
<div id="devices-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="devicesModal" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Choose device</h4>
</div>
<div class="modal-body">
<form id="particle-devices">
<div class="panel panel-default">
<ul class="list-group">
</ul>
</div>
<button id="btn-flash-device" type="submit" class="btn btn-primary btn-block" disabled="disabled">Flash firmware</button>
</form>
</div>
<div class="modal-footer">
<button id="btn-close-device-modal" type="button" class="btn btn-primary" data-dismiss="modal" disabled="disabled">Close</button>
</div>
</div>
</div>
</div>
<div class="container">
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="script.js"></script>
</body>
</html>
// display login modal
$('#login-modal').modal({
'backdrop': 'static'
});
// login functionality
$('#particle-login').submit(function(e) {
// get contents of login form (email, password)
var auth = $(this).serializeArray();
// create instance of particle token object (see below)
var particle = new Particle(auth[0].value, auth[1].value);
particle.createAccessToken(function(accessToken) {
// hide login modal
$('#login-modal').modal('hide');
// display device selection modal
$('#devices-modal').modal({
'backdrop': 'static'
});
particle.listDevices(accessToken, function(devices) {
// populate modal with list of devices
$.each(devices, function(k, v) {
$('#particle-devices .list-group').append(
'<li class="list-group-item">' +
'<div class="radio">' +
'<label>' +
'<input type="radio" name="optionsCores" id="optionsCores' + k + '" value="' + v.id + '">' + v.name +
'</label>' +
'</div>' +
'</li>'
);
});
// select device
$('#particle-devices').on('change', function() {
// get select device
var device = $(this).serializeArray();
// enable flash and close buttons
$('#btn-flash-device').prop('disabled', false);
$('#btn-close-device-modal').prop('disabled', false);
// flash device
$('#btn-flash-device').click(function(e) {
particle.flashDevice(device[0].value, accessToken);
e.preventDefault();
});
});
});
});
e.preventDefault();
});
// particle object
var Particle = function(username, password) {
this.getAccessTokens = function(success, error) {
$.ajax({
method: "GET",
url: "https://api.particle.io/v1/access_tokens",
beforeSend: function(xhr) {
// authorization header uses a base64 hash of email and password
xhr.setRequestHeader('Authorization', 'Basic ' + btoa(username + ':' + password));
},
success: function(accessTokens) {
if (success) success(accessTokens);
},
error: function(error) {
if (error) error();
}
})
};
this.createAccessToken = function(success, error) {
$.ajax({
method: "POST",
url: "https://api.particle.io/oauth/token",
data: {
'grant_type': 'password',
'username': username,
'password': password
},
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', 'Basic ' + btoa('particle:particle'));
},
success: function(accessToken) {
if (success) success(accessToken.access_token);
},
error: function(error) {
if (error) error();
}
})
};
this.deleteAccessToken = function(accessToken, success) {
$.ajax({
method: "DELETE",
url: "https://api.particle.io/v1/access_tokens/" + accessToken,
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', 'Basic ' + btoa(username + ':' + password));
},
success: function() {
if (success) success();
}
});
};
this.listDevices = function(accessToken, success) {
$.ajax({
method: "GET",
url: "https://api.particle.io/v1/devices",
data: {
'access_token': accessToken
},
success: function(devices) {
if (success) success(devices);
}
});
};
this.flashDevice = function(deviceId, accessToken) {
$.ajax({
method: "GET",
// url needs to be absolute to work in plnkr - hosted version should be relative url ("/firmware.ino") - this script will not work in a local environment
url: "http://run.plnkr.co/plunks/2M41bLuuEguGoFjqWVqj/firmware.ino",
success: function(file) {
// create file
var f = new File([file], "firmware.ino");
// create form-data object and add file to it
var form = new FormData();
form.append("file", f);
// put firmware onto device
$.ajax({
async: true,
crossDomain: true,
url: "https://api.particle.io/v1/devices/" + deviceId + "?access_token=" + accessToken,
method: "PUT",
headers: {},
processData: false,
contentType: false,
mimeType: "multipart/form-data",
data: form
});
}
});
};
};
body {
margin-top: 20px;
}
.alert,
#access-tokens,
#access-token-btn {
display: none;
}
int timeOn = 0;
int timeOff = 2000;
void setup() {
Spark.function("ssr", ssrControl);
pinMode(D7, OUTPUT);
}
void loop() {
delay(timeOff);
digitalWrite(D7, HIGH);
delay(timeOn);
digitalWrite(D7, LOW);
}
int ssrControl(String t) {
timeOn = atoi(t.c_str());
timeOff = 2000-timeOn;
return 1;
}