commit
5dc145396f
2
Gemfile
2
Gemfile
|
@ -26,6 +26,7 @@ end
|
|||
group :development, :test do
|
||||
gem 'pry'
|
||||
gem 'factory_girl_rails'
|
||||
gem 'faker'
|
||||
end
|
||||
|
||||
gem 'haml'
|
||||
|
@ -35,6 +36,7 @@ group :test do
|
|||
gem 'rspec-rails'
|
||||
gem 'simplecov'
|
||||
gem 'capybara'
|
||||
gem 'launchy' #save_and_open_page while debugging integration tests.
|
||||
end
|
||||
|
||||
gem 'devise', github: 'plataformatec/devise'
|
||||
|
|
58
Gemfile.lock
58
Gemfile.lock
|
@ -1,6 +1,6 @@
|
|||
GIT
|
||||
remote: git://github.com/mongoid/mongoid.git
|
||||
revision: 026e32109178eef2a50b31924f45eee2b7e05c82
|
||||
revision: e93a4837b0266db46c24aae172e184f57c847b04
|
||||
specs:
|
||||
mongoid (4.0.0.beta1)
|
||||
activemodel (>= 4.0.0)
|
||||
|
@ -10,7 +10,7 @@ GIT
|
|||
|
||||
GIT
|
||||
remote: git://github.com/plataformatec/devise.git
|
||||
revision: b0b18fb80508ae37a7460e1f6d1064adf9593cce
|
||||
revision: 6129215afecc0b3628e0d46f5253f89e2a862c6b
|
||||
specs:
|
||||
devise (3.2.4)
|
||||
bcrypt (~> 3.0)
|
||||
|
@ -48,9 +48,10 @@ GEM
|
|||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo (~> 1.1)
|
||||
arel (5.0.0)
|
||||
addressable (2.3.6)
|
||||
arel (5.0.1.20140414130214)
|
||||
bcrypt (3.1.7)
|
||||
bson (2.2.2)
|
||||
bson (2.2.3)
|
||||
builder (3.2.2)
|
||||
capybara (2.2.1)
|
||||
mime-types (>= 1.16)
|
||||
|
@ -71,14 +72,13 @@ GEM
|
|||
docile (1.1.3)
|
||||
erubis (2.7.0)
|
||||
execjs (2.0.2)
|
||||
<<<<<<< HEAD
|
||||
factory_girl (4.4.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.4.1)
|
||||
factory_girl (~> 4.4.0)
|
||||
railties (>= 3.0.0)
|
||||
=======
|
||||
>>>>>>> f3343624fe42bfb16f3428f39098c5913d4b0608
|
||||
faker (1.3.0)
|
||||
i18n (~> 0.5)
|
||||
haml (4.0.5)
|
||||
tilt
|
||||
high_voltage (2.1.0)
|
||||
|
@ -88,18 +88,20 @@ GEM
|
|||
activesupport (>= 3.0.0)
|
||||
multi_json (>= 1.2.0)
|
||||
json (1.8.1)
|
||||
launchy (2.4.2)
|
||||
addressable (~> 2.3)
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
method_source (0.8.2)
|
||||
mime-types (1.25.1)
|
||||
mini_portile (0.5.3)
|
||||
minitest (5.3.2)
|
||||
minitest (5.3.3)
|
||||
moped (2.0.0.rc1)
|
||||
bson (~> 2.2)
|
||||
connection_pool (~> 2.0)
|
||||
optionable (~> 0.2.0)
|
||||
multi_json (1.9.2)
|
||||
multi_json (1.10.0)
|
||||
nokogiri (1.6.1)
|
||||
mini_portile (~> 0.5.0)
|
||||
optionable (0.2.0)
|
||||
|
@ -133,30 +135,25 @@ GEM
|
|||
activesupport (= 4.1.0)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (10.2.2)
|
||||
rake (10.3.1)
|
||||
rdoc (4.1.1)
|
||||
json (~> 1.4)
|
||||
rspec (1.3.2)
|
||||
rspec-collection_matchers (0.0.4)
|
||||
rspec-expectations (>= 2.99.0.beta1)
|
||||
rspec-core (3.0.0.beta2)
|
||||
rspec-support (= 3.0.0.beta2)
|
||||
rspec-expectations (3.0.0.beta2)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (= 3.0.0.beta2)
|
||||
rspec-mocks (3.0.0.beta2)
|
||||
rspec-support (= 3.0.0.beta2)
|
||||
rspec-rails (3.0.0.beta2)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.8)
|
||||
rspec-expectations (2.14.5)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.6)
|
||||
rspec-rails (2.14.2)
|
||||
actionpack (>= 3.0)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-collection_matchers
|
||||
rspec-core (= 3.0.0.beta2)
|
||||
rspec-expectations (= 3.0.0.beta2)
|
||||
rspec-mocks (= 3.0.0.beta2)
|
||||
rspec-support (= 3.0.0.beta2)
|
||||
rspec-support (3.0.0.beta2)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
sass (3.2.19)
|
||||
sass-rails (4.0.3)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
|
@ -177,7 +174,7 @@ GEM
|
|||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sprockets-rails (2.1.1)
|
||||
sprockets-rails (2.1.3)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (~> 2.8)
|
||||
|
@ -204,13 +201,12 @@ DEPENDENCIES
|
|||
capybara
|
||||
coffee-rails
|
||||
devise!
|
||||
<<<<<<< HEAD
|
||||
factory_girl_rails
|
||||
=======
|
||||
>>>>>>> f3343624fe42bfb16f3428f39098c5913d4b0608
|
||||
faker
|
||||
haml
|
||||
high_voltage (~> 2.1.0)
|
||||
jbuilder (~> 1.2)
|
||||
launchy
|
||||
mongoid (~> 4.0.0.beta1)!
|
||||
pry
|
||||
rails (= 4.1.0)
|
||||
|
|
|
@ -17,8 +17,14 @@
|
|||
%a{href: "#"} Menu
|
||||
%section.top-bar-section
|
||||
%ul.left
|
||||
-if current_user
|
||||
%li{class: ("active" if current_page? page_path('dashboard'))}
|
||||
= link_to 'Dashboard', page_path('dashboard')
|
||||
%li{class: ("active" if current_page? page_path('data'))}
|
||||
= link_to 'Data', page_path('data') # TODO: View helper for these items.
|
||||
%li{class: ("active" if current_page? page_path('help'))}
|
||||
= link_to 'Help', page_path('help')
|
||||
|
||||
%ul.right
|
||||
- if current_user
|
||||
%li
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
<ul class="button-group even-4">
|
||||
<li><a href="#" class="button secondary"> Wed, Aug 21, 2:36 PM <span>74</span></a></li>
|
||||
<li><a href="#" class="button secondary"> $4.12/day <span>Water </span></a></li>
|
||||
<li><a href="#" class="button secondary"> $0.73/day <span>Pesticide </span></a></li>
|
||||
<li><a href="#" class="button secondary"> $1.19/day <span>Fertilizer </span></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="large-2 columns">
|
||||
<div class="panel">
|
||||
|
||||
<input type="text" placeholder="Search">
|
||||
<h5>My Plants & Operations</h5>
|
||||
|
||||
<ul class="large-block-grid-2">
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
<h5>All Plants & Operations</h5>
|
||||
|
||||
<ul class="large-block-grid-2">
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
<li><img src="http://placehold.it/100&text=Plant"></li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div><!-- End Panel -->
|
||||
</div><!-- End Large-2 -->
|
||||
|
||||
<div class="large-8 columns">
|
||||
<div class="panel">Farm Designer</div><!-- End Panel -->
|
||||
</div><!-- End Large-8 -->
|
||||
|
||||
<div class="large-2 columns">
|
||||
<div class="panel">
|
||||
|
||||
<input type="text" placeholder="Search">
|
||||
<h4>Operation Agenda</h4>
|
||||
<br>
|
||||
|
||||
<section>
|
||||
<h6>Wednesday, Aug 21</h6>
|
||||
<ul class="side-nav">
|
||||
<li class="active"><a href="#">4am Water 1, 2, 3, 4</a></li>
|
||||
<li><a href="#">10am Water 2, 3</a></li>
|
||||
<li><a href="#">1pm Till 5</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#">3pm Water 5</a></li>
|
||||
<li><a href="#">5pm Water 5</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h6>Thursday, Aug 22</h6>
|
||||
<ul class="side-nav">
|
||||
<li class="active"><a href="#">4am Water 1, 2, 3, 4</a></li>
|
||||
<li><a href="#">10am Water 2, 3</a></li>
|
||||
<li><a href="#">1pm Till 5</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#">3pm Water 5</a></li>
|
||||
<li><a href="#">5pm Water 5</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h6>Friday, Aug 23</h6>
|
||||
<ul class="side-nav">
|
||||
<li class="active"><a href="#">4am Water 1, 2, 3, 4</a></li>
|
||||
<li><a href="#">10am Water 2, 3</a></li>
|
||||
<li><a href="#">1pm Till 5</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#">3pm Water 5</a></li>
|
||||
<li><a href="#">5pm Water 5</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
</div><!-- End Panel -->
|
||||
</div><!-- End Large-2 -->
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- End Container -->
|
|
@ -0,0 +1,256 @@
|
|||
<ul class="button-group even-4">
|
||||
<li><a href="#" class="button secondary"> Wed, Aug 21, 2:36 PM <span>74</span></a></li>
|
||||
<li><a href="#" class="button secondary"> $4.12/day <span>Water </span></a></li>
|
||||
<li><a href="#" class="button secondary"> $0.73/day <span>Pesticide </span></a></li>
|
||||
<li><a href="#" class="button secondary"> $1.19/day <span>Fertilizer </span></a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- Side Bar -->
|
||||
|
||||
<div class="large-6 columns">
|
||||
|
||||
<div class="panel clearfix">
|
||||
|
||||
<div class="large-4 columns">
|
||||
|
||||
<h6>Farmbot</h6>
|
||||
|
||||
<dl class="accordion" data-accordion="">
|
||||
<dd class="">
|
||||
<a href="#panel1">Genesis Tracks</a>
|
||||
<div id="panel1" class="content">
|
||||
<p>Model: Genesis Tracks v2.6</p>
|
||||
<p>Length: 36 meters </p>
|
||||
<p>Width: 2 meters</p>
|
||||
<p>Height: 18 centimeters</p>
|
||||
<p>Installation date: 9/6/2013</p>
|
||||
</div>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="#panel2">Genesis Gantry</a>
|
||||
<div id="panel2" class="content">
|
||||
Panel 2. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="#panel3">Richmond Cross Slide</a>
|
||||
<div id="panel3" class="content">
|
||||
Panel 3. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
<dd class="">
|
||||
<a href="#panel4">Custom Tool Mount</a>
|
||||
<div id="panel4" class="content">
|
||||
Panel 3. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div><!-- end large-4 -->
|
||||
<div class="large-4 columns">
|
||||
|
||||
<h6>Tools</h6>
|
||||
|
||||
<dl class="accordion" data-accordion="">
|
||||
<dd class="">
|
||||
<a href="#panel5">Genesis Seed Injector</a>
|
||||
<div id="panel5" class="content">
|
||||
|
||||
</div>
|
||||
</dd>
|
||||
<dd class="">
|
||||
<a href="#panel6">FarmBot Pro Nozzle</a>
|
||||
<div id="panel6" class="content">
|
||||
Panel 2. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="#panel7">Precision Burner</a>
|
||||
<div id="panel7" class="content">
|
||||
Panel 3. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
<dd class="">
|
||||
<a href="#panel8">Alain Tiller</a>
|
||||
<div id="panel8" class="content">
|
||||
Panel 3. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
</div><!-- end large-4 -->
|
||||
<div class="large-4 columns">
|
||||
|
||||
<h6>Sensors</h6>
|
||||
|
||||
<dl class="accordion" data-accordion="">
|
||||
<dd class="">
|
||||
<a href="#panel9">Ambient Temperature</a>
|
||||
<div id="panel9" class="content">
|
||||
|
||||
</div>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="#panel10">Moisture Meter</a>
|
||||
<div id="panel10" class="content">
|
||||
Panel 2. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
<dd class="">
|
||||
<a href="#panel11">Genesis pH</a>
|
||||
<div id="panel11" class="content">
|
||||
Panel 3. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div><!-- end large-4 -->
|
||||
|
||||
</div> <!-- End Panel -->
|
||||
|
||||
<div class="panel">
|
||||
|
||||
<div class="container clearfix">
|
||||
<div class="large-4 columns">Gantry (X)</div>
|
||||
<div class="large-4 columns"><span class="label round success"><i class="fi-plus"></i></span> 46 <span class="label round alert"><i class="fi-minus"></i></span></div>
|
||||
<div class="large-4 columns">Jog to: </div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="container clearfix">
|
||||
<div class="large-4 columns">Cross-Slide (Y)</div>
|
||||
<div class="large-4 columns"><span class="label round success"><i class="fi-plus"></i></span> 46 <span class="label round alert"><i class="fi-minus"></i></span></div>
|
||||
<div class="large-4 columns">Jog to: </div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="container clearfix">
|
||||
<div class="large-4 columns">Tool Mount (Z)</div>
|
||||
<div class="large-4 columns"><span class="label round success"><i class="fi-plus"></i></span> 46 <span class="label round alert"><i class="fi-minus"></i></span></div>
|
||||
<div class="large-4 columns">Jog to: </div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
<ul class="button-group even-3">
|
||||
<li><a href="#" class="button small">Jog to Home</a></li>
|
||||
<li><a href="#" class="button small">Calibrate</a></li>
|
||||
<li><a href="#" class="button small alert">Shutdown</a></li>
|
||||
</ul>
|
||||
|
||||
</div> <!-- End Panel -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="#" data-reveal-id="myModal" data-reveal="">
|
||||
<div class="panel callout radius">
|
||||
<h6>View System Information</h6>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- End Side Bar -->
|
||||
|
||||
|
||||
<div id="myModal" class="reveal-modal" data-reveal="" style="display: none; opacity: 1; visibility: hidden; top: -665px;">
|
||||
<h2>System Information</h2>
|
||||
<p>Next operation in: 9 minutes (Watering)</p>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Thumbnails -->
|
||||
|
||||
<div class="large-6 columns">
|
||||
|
||||
|
||||
<div class="panel">
|
||||
|
||||
<nav class="top-bar" data-topbar="">
|
||||
<ul class="title-area">
|
||||
<li class="name">
|
||||
<h1><a href="#">Resource Usage</a></h1>
|
||||
</li>
|
||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul class="right">
|
||||
<li class="has-dropdown not-click">
|
||||
<a href="#">Plot 1: Nitrogen Fertilizer</a>
|
||||
<ul class="dropdown"><li class="title back js-generated"><h5><a href="javascript:void(0)">Back</a></h5></li>
|
||||
<li><a href="#">First link in dropdown</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="has-dropdown not-click">
|
||||
<a href="#">Plot 2: Water</a>
|
||||
<ul class="dropdown"><li class="title back js-generated"><h5><a href="javascript:void(0)">Back</a></h5></li>
|
||||
<li><a href="#">First link in dropdown</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</section></nav>
|
||||
|
||||
|
||||
<div class="panel-chart"><img src="http://placehold.it/1000x400&text=Graph"></div>
|
||||
</div><!-- end panel -->
|
||||
|
||||
|
||||
<div class="panel">
|
||||
|
||||
<nav class="top-bar" data-topbar="">
|
||||
<ul class="title-area">
|
||||
<li class="name">
|
||||
<h1><a href="#">Finances</a></h1>
|
||||
</li>
|
||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul class="right">
|
||||
<li class="has-dropdown not-click">
|
||||
<a href="#">Plot 1: Revenue</a>
|
||||
<ul class="dropdown"><li class="title back js-generated"><h5><a href="javascript:void(0)">Back</a></h5></li>
|
||||
<li><a href="#">First link in dropdown</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="has-dropdown not-click">
|
||||
<a href="#">Plot 2: Expenditures</a>
|
||||
<ul class="dropdown"><li class="title back js-generated"><h5><a href="javascript:void(0)">Back</a></h5></li>
|
||||
<li><a href="#">First link in dropdown</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</section></nav>
|
||||
|
||||
|
||||
<div class="panel-chart"><img src="http://placehold.it/1000x400&text=Graph"></div>
|
||||
</div><!-- end panel -->
|
||||
|
||||
</div><!-- End Thumbnails -->
|
||||
|
||||
|
||||
|
||||
</div><!-- End Container -->
|
|
@ -25,5 +25,13 @@ module Dss
|
|||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
# config.i18n.default_locale = :de
|
||||
|
||||
config.generators do |g|
|
||||
g.template_engine :haml
|
||||
g.test_framework :rspec, :fixture_replacement => :factory_girl, :views => false, :helper => false
|
||||
g.view_specs false
|
||||
g.helper_specs false
|
||||
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
development:
|
||||
# Configure available database sessions. (required)
|
||||
sessions:
|
||||
# Defines the default session. (required)
|
||||
default:
|
||||
# Defines the name of the default database that Mongoid can connect to.
|
||||
# (required).
|
||||
database: farmbot_backend_development
|
||||
# Provides the hosts the default session can connect to. Must be an array
|
||||
# of host:port pairs. (required)
|
||||
hosts:
|
||||
- localhost:27017
|
||||
options:
|
||||
# Change the default write concern. (default = { w: 1 })
|
||||
# write:
|
||||
# w: 1
|
||||
|
||||
# Change the default consistency model to primary, secondary.
|
||||
# 'secondary' will send reads to secondaries, 'primary' sends everything
|
||||
# to master. (default: primary)
|
||||
# read: secondary_preferred
|
||||
|
||||
# How many times Moped should attempt to retry an operation after
|
||||
# failure. (default: 30)
|
||||
# max_retries: 30
|
||||
|
||||
# The time in seconds that Moped should wait before retrying an
|
||||
# operation on failure. (default: 1)
|
||||
# retry_interval: 1
|
||||
# Configure Mongoid specific options. (optional)
|
||||
options:
|
||||
# Enable the identity map, needed for eager loading. (default: false)
|
||||
# identity_map_enabled: false
|
||||
|
||||
# Includes the root model name in json serialization. (default: false)
|
||||
# include_root_in_json: false
|
||||
|
||||
# Include the _type field in serializaion. (default: false)
|
||||
# include_type_for_serialization: false
|
||||
|
||||
# Preload all models in development, needed when models use
|
||||
# inheritance. (default: false)
|
||||
# preload_models: false
|
||||
|
||||
# Protect id and type from mass assignment. (default: true)
|
||||
# protect_sensitive_fields: true
|
||||
|
||||
# Raise an error when performing a #find and the document is not found.
|
||||
# (default: true)
|
||||
# raise_not_found_error: true
|
||||
|
||||
# Raise an error when defining a scope with the same name as an
|
||||
# existing method. (default: false)
|
||||
# scope_overwrite_exception: false
|
||||
|
||||
# Skip the database version check, used when connecting to a db without
|
||||
# admin access. (default: false)
|
||||
# skip_version_check: false
|
||||
|
||||
# Use Active Support's time zone in conversions. (default: true)
|
||||
# use_activesupport_time_zone: true
|
||||
|
||||
# Ensure all times are UTC in the app side. (default: false)
|
||||
# use_utc: false
|
||||
test:
|
||||
sessions:
|
||||
default:
|
||||
database: farmbot_backend_test
|
||||
hosts:
|
||||
- localhost:27017
|
||||
options:
|
||||
read: primary
|
||||
# In the test environment we lower the retries and retry interval to
|
||||
# low amounts for fast failures.
|
||||
max_retries: 1
|
||||
retry_interval: 0
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
:uuid: 40b8cfdf-92e9-450d-b603-1e9efbbecf47
|
||||
:token: !binary |-
|
||||
MzIwMTc3M2IwZDA3N2NmM2ZlZmQ5ZDQwZjNiZGE1NmI=
|
|
@ -1,71 +0,0 @@
|
|||
|
||||
# ####################################
|
||||
# Send something to farmbot controller
|
||||
# ####################################
|
||||
|
||||
class FarmBotControllerComm
|
||||
|
||||
# send command to farmbot
|
||||
def send_single_command(action, x, y, z, amount, speed, delay)
|
||||
|
||||
$skynet.confirmed = false
|
||||
command =
|
||||
{
|
||||
:message_type => 'single_command',
|
||||
:time_stamp => Time.now.to_f.to_s,
|
||||
:command => {
|
||||
:action => action,
|
||||
:x => x,
|
||||
:y => y,
|
||||
:z => z,
|
||||
:speed => speed,
|
||||
:amount => amount,
|
||||
:delay => delay
|
||||
}}
|
||||
|
||||
|
||||
$skynet.send_message($farmbot_uuid, command)
|
||||
return wait_for_confirmation()
|
||||
|
||||
end
|
||||
|
||||
|
||||
# send schedule to farmbot
|
||||
def send_schedule(uuid, schedule)
|
||||
|
||||
$skynet.confirmed = false
|
||||
|
||||
sched_hash = schedule.to_hash
|
||||
sched_hash[:message_type] = 'crop_schedule_update'
|
||||
sched_hash[:time_stamp] = Time.now.to_f.to_s
|
||||
|
||||
puts sched_hash
|
||||
|
||||
$skynet.send_message(uuid, sched_hash)
|
||||
return wait_for_confirmation()
|
||||
|
||||
end
|
||||
|
||||
def wait_for_confirmation
|
||||
puts 'waiting for confirmation'
|
||||
count = 0
|
||||
while $skynet.confirmed != true and count < 10
|
||||
sleep 0.5
|
||||
print '.'
|
||||
count += 1
|
||||
end
|
||||
|
||||
puts ''
|
||||
|
||||
if $skynet.confirmed
|
||||
puts 'confirmation received'
|
||||
return true
|
||||
else
|
||||
puts 'confirmation timed out'
|
||||
sleep 2
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,118 +0,0 @@
|
|||
|
||||
#
|
||||
# Classes to make a schedule that can be transmitted to the bot
|
||||
#
|
||||
|
||||
class CropSchedule
|
||||
|
||||
attr_accessor :crop_id
|
||||
|
||||
def initialize
|
||||
@commands = Array.new
|
||||
end
|
||||
|
||||
def read_from_db(crop)
|
||||
@crop_id = crop.crop_id
|
||||
|
||||
crop.scheduled_commands.each do |dbcommand|
|
||||
|
||||
command = CropScheduleCommand.new
|
||||
command.read_from_db(dbcommand)
|
||||
add_command(command)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def to_hash
|
||||
command_nr = 0
|
||||
schedule_hash = {:crop_id => @crop_id, :commands => {} }
|
||||
commands = Hash.new
|
||||
@commands.each do |command|
|
||||
command_nr += 1
|
||||
commands["command_#{command_nr}"]= command.to_hash
|
||||
end
|
||||
schedule_hash[:commands] = commands
|
||||
return schedule_hash
|
||||
end
|
||||
|
||||
def add_command(command)
|
||||
|
||||
@commands << command
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CropScheduleCommand
|
||||
|
||||
attr_accessor :scheduled_time
|
||||
|
||||
def initialize
|
||||
@command_lines = Array.new
|
||||
end
|
||||
|
||||
def read_from_db(command)
|
||||
puts command
|
||||
puts command.scheduled_time
|
||||
@scheduled_time = command.scheduled_time
|
||||
seq = 0
|
||||
|
||||
command.scheduled_command_lines.each do |dbline|
|
||||
|
||||
seq += 1
|
||||
line = CropScheduleCommandLine.new
|
||||
line.read_from_db(dbline, seq)
|
||||
add_command_line(line)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def to_hash
|
||||
sequence_nr = 0
|
||||
command_hash = {:scheduled_time => @scheduled_time, :command_lines => {} }
|
||||
command_lines = Hash.new
|
||||
@command_lines.each do |line|
|
||||
sequence_nr += 1
|
||||
line.sequence_nr = sequence_nr
|
||||
command_lines["command_line_#{sequence_nr}"]= line.to_hash
|
||||
end
|
||||
command_hash[:command_lines] = command_lines
|
||||
return command_hash
|
||||
end
|
||||
|
||||
def add_command_line(line)
|
||||
@command_lines << line
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CropScheduleCommandLine
|
||||
|
||||
attr_accessor :action, :x, :y, :z, :amount, :speed, :sequence_nr
|
||||
|
||||
def read_from_db(line, sequence_nr)
|
||||
@action = line.action
|
||||
@x = line.coord_x
|
||||
@y = line.coord_y
|
||||
@z = line.coord_z
|
||||
@amount = line.amount
|
||||
@speed = line.speed
|
||||
@sequence_nr = sequence_nr
|
||||
end
|
||||
|
||||
def to_hash
|
||||
|
||||
line = {
|
||||
:action => @action ,
|
||||
:x => @x ,
|
||||
:y => @y ,
|
||||
:z => @z ,
|
||||
:amount => @amount ,
|
||||
:speed => @speed ,
|
||||
:sequence_nr => @sequence_nr
|
||||
}
|
||||
return line
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,157 +0,0 @@
|
|||
require 'bson'
|
||||
require 'mongo'
|
||||
require 'mongoid'
|
||||
|
||||
# Data classes
|
||||
# This class is dedicated to retrieving and inserting commands into the schedule
|
||||
# queue for the farm bot Mongo is used as the database, Mongoid as the
|
||||
# databasemapper
|
||||
|
||||
class Command
|
||||
include Mongoid::Document
|
||||
|
||||
embeds_many :commandlines
|
||||
|
||||
field :plant_id
|
||||
field :crop_id
|
||||
field :scheduled_time
|
||||
field :executed_time
|
||||
field :status
|
||||
|
||||
end
|
||||
|
||||
class Commandline
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :command
|
||||
#belongs_to :command
|
||||
|
||||
field :action
|
||||
field :coord_x
|
||||
field :coord_y
|
||||
field :coord_z
|
||||
field :speed
|
||||
field :amount
|
||||
end
|
||||
|
||||
class Refresh
|
||||
include Mongoid::Document
|
||||
|
||||
field :name
|
||||
field :value
|
||||
end
|
||||
|
||||
# Access class for the database
|
||||
|
||||
class DbAccess
|
||||
|
||||
def initialize
|
||||
Mongoid.load!("config/mongo.yml", :development)
|
||||
@last_command_retrieved = nil
|
||||
@refresh_value = 0
|
||||
@refresh_value_new = 0
|
||||
|
||||
@new_command = nil
|
||||
end
|
||||
|
||||
def test
|
||||
db_connection = Mongo::Connection.new
|
||||
db_farmbot = db_connection['farmbot_development']
|
||||
db_schedule = db_farmbot['schedule']
|
||||
|
||||
db_connection.database_names.each do |name|
|
||||
db = db_connection.db(name)
|
||||
db.collections.each do |collection|
|
||||
puts "#{name} - #{collection.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_new_command(scheduled_time, crop_id)
|
||||
@new_command = Command.new
|
||||
@new_command.scheduled_time = scheduled_time
|
||||
@new_command.crop_id = crop_id
|
||||
end
|
||||
|
||||
def add_command_line(action, x = 0, y = 0, z = 0, speed = 0, amount = 0)
|
||||
if @new_command != nil
|
||||
line = Commandline.new
|
||||
line.action = action
|
||||
line.coord_x = x
|
||||
line.coord_y = y
|
||||
line.coord_z = z
|
||||
line.speed = speed
|
||||
line.amount = amount
|
||||
if @new_command.commandlines == nil
|
||||
@new_command.commandlines = [ line ]
|
||||
else
|
||||
@new_command.commandlines << line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def save_new_command
|
||||
if @new_command != nil
|
||||
@new_command.status = 'scheduled'
|
||||
@new_command.save
|
||||
end
|
||||
increment_refresh
|
||||
end
|
||||
|
||||
def clear_schedule
|
||||
Command.where(
|
||||
:status => 'scheduled',
|
||||
:scheduled_time.ne => nil
|
||||
).order_by([:scheduled_time,:asc]).each do |command|
|
||||
|
||||
command.status = 'deleted'
|
||||
command.save
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def clear_crop_schedule(crop_id)
|
||||
Command.where(
|
||||
:status => 'scheduled',
|
||||
:scheduled_time.ne => nil,
|
||||
:crop_id => crop_id
|
||||
).order_by([:scheduled_time,:asc]).each do |command|
|
||||
|
||||
command.status = 'deleted'
|
||||
command.save
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def get_command_to_execute
|
||||
@last_command_retrieved = Command.where(
|
||||
:status => 'scheduled',
|
||||
:scheduled_time.ne => nil
|
||||
).order_by([:scheduled_time,:asc]).first
|
||||
@last_command_retrieved
|
||||
end
|
||||
|
||||
def set_command_to_execute_status(new_status)
|
||||
if @last_command_retrieved != nil
|
||||
@last_command_retrieved.status = new_status
|
||||
@last_command_retrieved.save
|
||||
end
|
||||
end
|
||||
|
||||
def check_refresh
|
||||
r = Refresh.where(:name => 'FarmBotControllerSchedule').first_or_initialize
|
||||
@refresh_value_new = r.value.to_i
|
||||
return @refresh_value_new != @refresh_value
|
||||
end
|
||||
|
||||
def save_refresh
|
||||
@refresh_value = @refresh_value_new
|
||||
end
|
||||
|
||||
def increment_refresh
|
||||
r = Refresh.where(:name => 'FarmBotControllerSchedule').first_or_initialize
|
||||
r.value = r.value.to_i + 1
|
||||
r.save
|
||||
end
|
||||
|
||||
end
|
|
@ -1,134 +0,0 @@
|
|||
# This module holds our data definitions to store all basic plant and watering data
|
||||
# Mongo is used as the database, Mongoid as the databasemapper
|
||||
|
||||
require 'bson'
|
||||
require 'mongo'
|
||||
require 'mongoid'
|
||||
|
||||
#require 'bson_ext'
|
||||
|
||||
# The different farmbots are stored here
|
||||
|
||||
class FarmBot
|
||||
include Mongoid::Document
|
||||
|
||||
embeds_many :crops
|
||||
|
||||
field :active
|
||||
field :name
|
||||
field :environmental_coefficient
|
||||
field :uuid
|
||||
|
||||
# also needs user settings, security and whatsnot
|
||||
|
||||
end
|
||||
|
||||
# The list of crops tended by one farm bot. The crop is planted as a seed (age = 0) or when it has already sprouted.
|
||||
# Coordinates x, y and z are used to drive the robot to the right place
|
||||
# The age of maturing and harvesting should be customized to local conditions
|
||||
|
||||
class Crop
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :farmbot
|
||||
embeds_many :grow_coefficients
|
||||
embeds_many :waterings
|
||||
embeds_many :historic_actions
|
||||
embeds_many :scheduled_commands
|
||||
|
||||
field :plant_type
|
||||
field :coord_x
|
||||
field :coord_y
|
||||
field :coord_z
|
||||
field :radius
|
||||
field :height
|
||||
field :status
|
||||
|
||||
field :date_at_planting
|
||||
field :age_at_planting
|
||||
field :age_at_fully_grown
|
||||
field :age_at_harvest
|
||||
|
||||
field :valid_data
|
||||
field :crop_id
|
||||
|
||||
end
|
||||
|
||||
# Coefficients are used by the evapotransporation system. It expresses the amount of water (mm/day) the plant needs for a good growth at a certain age
|
||||
# The values for the coefficient is the result of the local climate reference value multiplied with the
|
||||
# The age is represented as a precentage, where 100% is fully grown and 200% is ready for harvesting
|
||||
|
||||
# a typical curve for a crops. the Y axis is here a multiplication factor for the reference crops (fictional grass or alfalfa)
|
||||
#
|
||||
# 1.0 *****
|
||||
# *| **
|
||||
# * | ***
|
||||
# * | |
|
||||
# ** | |
|
||||
# 0.1 *** | |
|
||||
# | | |
|
||||
# 0% 100% 200%
|
||||
|
||||
class GrowCoefficient
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :crop
|
||||
|
||||
field :age_in_percentage
|
||||
field :amount_water_manual
|
||||
|
||||
end
|
||||
|
||||
# These are the times when the robot is supposed to water the crop
|
||||
|
||||
class Watering
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :crop
|
||||
|
||||
field :time
|
||||
field :percentage
|
||||
end
|
||||
|
||||
# A log of what happended to the plant. Waterings and rainfall are the most important probably
|
||||
|
||||
class HistoricAction
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :crop
|
||||
|
||||
field :start_time
|
||||
field :stop_time
|
||||
field :action
|
||||
field :amount
|
||||
end
|
||||
|
||||
# This is the schedule for the next hours/days that the bot has to execute. This is synchronized to the bot.
|
||||
|
||||
class ScheduledCommand
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :crop
|
||||
embeds_many :scheduled_command_lines
|
||||
|
||||
|
||||
field :crop_id
|
||||
field :schedule_id
|
||||
field :one_time_command
|
||||
field :scheduled_time
|
||||
field :command_id
|
||||
end
|
||||
|
||||
class ScheduledCommandLine
|
||||
include Mongoid::Document
|
||||
|
||||
embedded_in :scheduled_command
|
||||
|
||||
field :action
|
||||
field :coord_x
|
||||
field :coord_y
|
||||
field :coord_z
|
||||
field :speed
|
||||
field :amount
|
||||
end
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
|
||||
require_relative 'skynet/skynet'
|
||||
|
||||
# The unfortunate use of globals in this project: The SocketIO library we use to
|
||||
# talk to skynet stores blocks as lambdas and calls them later under a different
|
||||
# context than that which they were defined. This means that even though we
|
||||
# define the .on() events within the `Device` class, self does NOT refer to the
|
||||
# device, but rather the current socket connection. Using a global is a quick
|
||||
# fix to ensure we always have easy access to the device. Pull requests welcome.
|
||||
|
||||
$skynet = Skynet.new
|
||||
|
||||
#TODO: Daemonize this script:
|
||||
#https://www.ruby-toolbox.com/categories/daemonizing
|
|
@ -1,49 +0,0 @@
|
|||
require 'securerandom'
|
||||
|
||||
module Credentials
|
||||
# Stores a references to the credentials yml file, which is used to persist
|
||||
# the user's skynet Token / ID across sessions. Returns String. parameterless
|
||||
def credentials_file
|
||||
'credentials.yml'
|
||||
end
|
||||
|
||||
# Returns Hash containing the a :uuid and :token key. Triggers the creation of
|
||||
# new credentials if the current ones are found to be invalid.
|
||||
def credentials
|
||||
if valid_credentials?
|
||||
return load_credentials
|
||||
else
|
||||
return create_credentials
|
||||
end
|
||||
end
|
||||
|
||||
# Validates that the credentials file has a :uuid and :token key. Returns Bool
|
||||
#
|
||||
def valid_credentials?
|
||||
if File.file?(credentials_file)
|
||||
cred = load_credentials
|
||||
return true if cred.has_key?(:uuid) && cred.has_key?(:token)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Uses the ruby securerandom library to make a new :uuid and :token. Also
|
||||
# registers with a new device :uuid and :token on skynet.im . Returns Hash
|
||||
# containing :uuid and :token key.
|
||||
def create_credentials
|
||||
hash = {
|
||||
uuid: (@uuid = SecureRandom.uuid),
|
||||
token: (@token = SecureRandom.hex)
|
||||
}
|
||||
`curl -s -X POST -d 'uuid=#{@uuid}&token=#{@token}&type=farmbot' \
|
||||
http://skynet.im/devices`
|
||||
File.open(credentials_file, 'w+') {|file| file.write(hash.to_yaml) }
|
||||
return hash
|
||||
end
|
||||
|
||||
### Loads the credentials file from disk and returns it as a ruby hash.
|
||||
def load_credentials
|
||||
return YAML.load(File.read(credentials_file))
|
||||
end
|
||||
|
||||
end
|
|
@ -1,201 +0,0 @@
|
|||
require 'json'
|
||||
#require './lib/database/commandqueue.rb'
|
||||
require './lib/database/dbcommand.rb'
|
||||
require 'time'
|
||||
|
||||
# Get the JSON command, received through skynet, and send it to the farmbot
|
||||
# command queue Parses JSON messages received through SkyNet.
|
||||
class MessageHandler
|
||||
|
||||
attr_accessor :message
|
||||
|
||||
def initialize
|
||||
@dbaccess = DbAccess.new
|
||||
@last_time_stamp = ''
|
||||
end
|
||||
|
||||
# A list of MessageHandler methods (as strings) that a Skynet User may access.
|
||||
#
|
||||
def whitelist
|
||||
["single_command","crop_schedule_update"]
|
||||
end
|
||||
|
||||
# Main entry point for (Hash) commands coming in over SkyNet.
|
||||
# {
|
||||
# "message_type" : "single_command",
|
||||
# "time_stamp" : 2001-01-01 01:01:01.001
|
||||
# "command" : {
|
||||
# "action" : "HOME X",
|
||||
# "x" : 1,
|
||||
# "y" : 2,
|
||||
# "z" : 3,
|
||||
# "speed" : "FAST",
|
||||
# "amount" : 5,
|
||||
# "delay" : 6
|
||||
# }
|
||||
# }
|
||||
|
||||
def handle_message(message)
|
||||
|
||||
puts 'handle_message'
|
||||
#puts message
|
||||
#puts message['message']
|
||||
|
||||
@message = message['message']
|
||||
#fromUuid = message['fromUuid']
|
||||
#puts fromUuid
|
||||
|
||||
requested_command = message['message']["message_type"].to_s.downcase
|
||||
#puts requested_command
|
||||
|
||||
if whitelist.include?(requested_command)
|
||||
#puts 'sending'
|
||||
self.send(requested_command, message)
|
||||
else
|
||||
self.error(message)
|
||||
end
|
||||
end
|
||||
|
||||
# Handles an erorr (typically, an unauthorized or unknown message). Returns
|
||||
# Hash.
|
||||
def error
|
||||
return {error: ""}
|
||||
end
|
||||
|
||||
def single_command(message)
|
||||
|
||||
puts 'single_command'
|
||||
#puts message
|
||||
|
||||
time_stamp = message['message']['time_stamp']
|
||||
sender = message['fromUuid']
|
||||
|
||||
if time_stamp != @last_time_stamp
|
||||
@last_time_stamp = time_stamp
|
||||
|
||||
|
||||
# send the command to the queue
|
||||
delay = message['message']['command']['delay']
|
||||
action = message['message']['command']['action']
|
||||
x = message['message']['command']['x']
|
||||
y = message['message']['command']['y']
|
||||
z = message['message']['command']['z']
|
||||
speed = message['message']['command']['speed']
|
||||
amount = message['message']['command']['amount']
|
||||
delay = message['message']['command']['delay']
|
||||
|
||||
puts "[new command] received at #{Time.now} from #{sender}"
|
||||
puts "[#{action}] x: #{x}, y: #{y}, z: #{z}, speed: #{speed}, amount: #{amount} delay: #{delay}"
|
||||
|
||||
@dbaccess.create_new_command(Time.now + delay.to_i,'single_command')
|
||||
@dbaccess.add_command_line(action, x.to_i, y.to_i, z.to_i, speed.to_s, amount.to_i)
|
||||
@dbaccess.save_new_command
|
||||
|
||||
$skynet.confirmed = false
|
||||
|
||||
command =
|
||||
{
|
||||
:message_type => 'confirmation',
|
||||
:time_stamp => Time.now.to_f.to_s,
|
||||
:confirm_id => time_stamp
|
||||
}
|
||||
|
||||
$skynet.send_message(sender, command)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def crop_schedule_update(message)
|
||||
|
||||
puts 'crop_schedule_update'
|
||||
#puts message
|
||||
|
||||
time_stamp = message['message']['time_stamp']
|
||||
sender = message['fromUuid']
|
||||
|
||||
puts "time_stamp #{time_stamp}"
|
||||
puts "sender #{sender}"
|
||||
|
||||
if time_stamp != @last_time_stamp
|
||||
@last_time_stamp = time_stamp
|
||||
|
||||
|
||||
message_contents = message['message']
|
||||
#puts message_contents
|
||||
|
||||
crop_id = message_contents['crop_id']
|
||||
puts crop_id
|
||||
|
||||
puts 'removing old crop schedule'
|
||||
@dbaccess.clear_crop_schedule(crop_id)
|
||||
|
||||
message_contents['commands'].each do |command|
|
||||
|
||||
#puts command
|
||||
#puts command.class
|
||||
#puts command[0]
|
||||
#puts command[0].class
|
||||
#puts command[1]
|
||||
#puts command[1].class
|
||||
|
||||
scheduled_time = Time.parse(command[1]['scheduled_time'])
|
||||
|
||||
@dbaccess.create_new_command(scheduled_time, crop_id)
|
||||
#@dbaccess.create_new_command(Time.now, 'debug')
|
||||
puts scheduled_time
|
||||
puts Time.now
|
||||
|
||||
command[1]['command_lines'].each do |command_line|
|
||||
|
||||
action = command_line[1]['action']
|
||||
x = command_line[1]['x']
|
||||
y = command_line[1]['y']
|
||||
z = command_line[1]['z']
|
||||
speed = command_line[1]['speed']
|
||||
amount = command_line[1]['amount']
|
||||
|
||||
|
||||
puts "[#{action}] x: #{x}, y: #{y}, z: #{z}, speed: #{speed}, amount: #{amount}"
|
||||
@dbaccess.add_command_line(action, x.to_i, y.to_i, z.to_i, speed.to_s, amount.to_i)
|
||||
|
||||
end
|
||||
|
||||
@dbaccess.save_new_command
|
||||
|
||||
end
|
||||
|
||||
# send the command to the queue
|
||||
#delay = message['message']['command']['delay']
|
||||
#action = message['message']['command']['action']
|
||||
#x = message['message']['command']['x']
|
||||
#y = message['message']['command']['y']
|
||||
#z = message['message']['command']['z']
|
||||
#speed = message['message']['command']['speed']
|
||||
#amount = message['message']['command']['amount']
|
||||
#delay = message['message']['command']['delay']
|
||||
|
||||
#puts "[new command] received at #{Time.now} from #{sender}"
|
||||
#puts "[#{action}] x: #{x}, y: #{y}, z: #{z}, speed: #{speed}, amount: #{amount} delay: #{delay}"
|
||||
|
||||
#@dbaccess.create_new_command(Time.now + delay.to_i)
|
||||
#@dbaccess.add_command_line(action, x.to_i, y.to_i, z.to_i, speed.to_s, amount.to_i)
|
||||
#@dbaccess.save_new_command
|
||||
|
||||
puts 'sending comfirmation'
|
||||
|
||||
$skynet.confirmed = false
|
||||
|
||||
command =
|
||||
{
|
||||
:message_type => 'confirmation',
|
||||
:time_stamp => Time.now.to_f.to_s,
|
||||
:confirm_id => time_stamp
|
||||
}
|
||||
|
||||
$skynet.send_message(sender, command)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -1,59 +0,0 @@
|
|||
require 'json'
|
||||
|
||||
require_relative 'credentials'
|
||||
require_relative 'web_socket'
|
||||
require_relative 'messagehandler.rb'
|
||||
|
||||
# The Device class is temporarily inheriting from Tim's HardwareInterface.
|
||||
# Eventually, we should merge the two projects, but this is good enough for now.
|
||||
class Skynet
|
||||
|
||||
include Credentials, WebSocket
|
||||
|
||||
attr_accessor :socket, :uuid, :token, :identified, :confirmed,
|
||||
:confirmation_id
|
||||
|
||||
# On instantiation #new sets the @uuid, @token variables, connects to skynet
|
||||
def initialize
|
||||
super
|
||||
identified = false
|
||||
creds = credentials
|
||||
@uuid = creds[:uuid]
|
||||
@token = creds[:token]
|
||||
@socket = SocketIO::Client::Simple.connect 'http://skynet.im:80'
|
||||
@confirmed = false
|
||||
|
||||
create_socket_events
|
||||
|
||||
puts "uuid: #{@uuid}"
|
||||
|
||||
@message_handler = MessageHandler.new
|
||||
end
|
||||
|
||||
def send_message(devices, message_hash )
|
||||
@socket.emit("message",{:devices => devices, :message => message_hash})
|
||||
end
|
||||
|
||||
# Acts as the entry point for message traffic captured from Skynet.im.
|
||||
# This method is a stub for now until I have time to merge into Tim's
|
||||
# controller code. Returns a MessageHandler object (a class yet created).
|
||||
#def handle_message(channel, message)
|
||||
def handle_message(message)
|
||||
|
||||
puts "> message received at #{Time.now}"
|
||||
#puts message
|
||||
|
||||
if message.class.to_s == 'Hash'
|
||||
@message_handler.handle_message(message)
|
||||
end
|
||||
|
||||
if message.class.to_s == 'String'
|
||||
message_hash = JSON.parse(message)
|
||||
@message_handler.handle_message(message_hash)
|
||||
end
|
||||
|
||||
rescue
|
||||
raise "Runtime error while attempting to parse message: #{message}."
|
||||
end
|
||||
|
||||
end
|
|
@ -1,33 +0,0 @@
|
|||
require 'socket.io-client-simple'
|
||||
|
||||
module WebSocket
|
||||
### Bootstraps all the events for skynet in the correct order. Returns Int.
|
||||
def create_socket_events
|
||||
#OTHER EVENTS: :identify, :identity, :ready, :disconnect, :message
|
||||
create_identify_event
|
||||
create_message_event
|
||||
end
|
||||
|
||||
#Handles self identification on skynet by responding to the :indentify with a
|
||||
#:identity event / credentials Hash.
|
||||
def create_identify_event
|
||||
@socket.on :identify do |data|
|
||||
self.emit :identity, {
|
||||
uuid: $skynet.uuid,
|
||||
token: $skynet.token,
|
||||
socketid: data['socketid']}
|
||||
$skynet.identified = true
|
||||
end
|
||||
end
|
||||
|
||||
### Routes all skynet messages to handle_event() for interpretation.
|
||||
def create_message_event
|
||||
#@socket.on :message do |channel, message|
|
||||
# $skynet.handle_message(channel, message)
|
||||
#end
|
||||
@socket.on :message do |message|
|
||||
$skynet.handle_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,44 +0,0 @@
|
|||
|
||||
$farmbot_uuid = "063df52b-0698-4e1c-b2bb-4c0890019782"
|
||||
|
||||
require_relative 'lib/skynet/skynet'
|
||||
require_relative 'lib/botcomm'
|
||||
require_relative 'lib/cropschedule'
|
||||
require_relative 'lib/database/dbcommand'
|
||||
require_relative 'lib/database/dbfarmbot'
|
||||
|
||||
puts '[FarmBot schedule transmit]'
|
||||
puts 'starting up'
|
||||
|
||||
# connecting to skynet framework
|
||||
$skynet = Skynet.new
|
||||
|
||||
$farmbot_comm = FarmBotControllerComm.new
|
||||
|
||||
while $skynet.identified != true
|
||||
sleep 0.5
|
||||
print '.'
|
||||
end
|
||||
puts ''
|
||||
|
||||
puts 'connecting to database'
|
||||
|
||||
Mongoid.load!("config/mongo.yml", :development)
|
||||
|
||||
puts 'checking list of bots'
|
||||
|
||||
FarmBot.where(:active => true).order_by([:name,:asc]).each do |farmbot|
|
||||
puts "checking bot #{farmbot.name} uuid #(farmbot.uuid)"
|
||||
|
||||
farmbot.crops.where(:valid_data => true).each do |crop|
|
||||
|
||||
puts "crop type=#{crop.plant_type} @ x=#{crop.coord_x} y=#{crop.coord_y}"
|
||||
|
||||
crop_schedule = CropSchedule.new
|
||||
crop_schedule.read_from_db( crop )
|
||||
|
||||
$farmbot_comm.send_schedule(farmbot.uuid,crop_schedule)
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,104 +0,0 @@
|
|||
|
||||
$farmbot_uuid = "063df52b-0698-4e1c-b2bb-4c0890019782"
|
||||
|
||||
require_relative 'lib/device/device'
|
||||
require_relative 'lib/botcomm'
|
||||
|
||||
puts '[FarmBot Remote Control]'
|
||||
puts 'starting up'
|
||||
|
||||
# connecting to skynet framework
|
||||
$device = Device.new
|
||||
|
||||
$farmbot_comm = FarmBotControllerComm.new
|
||||
|
||||
while $device.identified != true
|
||||
sleep 0.5
|
||||
print '.'
|
||||
end
|
||||
puts ''
|
||||
|
||||
# send schedule to farmbot
|
||||
def send_singe_command(action, x, y, z, amount, speed, delay)
|
||||
|
||||
$farmbot_comm.send_single_command(action, x, y, z, amount, speed, delay)
|
||||
|
||||
end
|
||||
|
||||
|
||||
$shutdown = 0
|
||||
|
||||
# just a little menu for testing
|
||||
|
||||
$move_size = 10
|
||||
$command_delay = 0
|
||||
|
||||
while $shutdown == 0 do
|
||||
|
||||
system('cls')
|
||||
system('clear')
|
||||
|
||||
puts '[FarmBot Controller Menu]'
|
||||
puts ''
|
||||
puts 'p - stop'
|
||||
puts ''
|
||||
puts "move size = #{$move_size}"
|
||||
puts "command delay = #{$command_delay}"
|
||||
puts ''
|
||||
puts 'w - forward'
|
||||
puts 's - back'
|
||||
puts 'a - left'
|
||||
puts 'd - right'
|
||||
puts 'r - up'
|
||||
puts 'f - down'
|
||||
puts ''
|
||||
puts 'z - home z axis'
|
||||
puts 'x - home x axis'
|
||||
puts 'c - home y axis'
|
||||
puts ''
|
||||
puts 'y - dose water'
|
||||
puts ''
|
||||
puts 'q - step size'
|
||||
puts 'g - delay seconds'
|
||||
puts ''
|
||||
print 'command > '
|
||||
input = gets
|
||||
puts ''
|
||||
|
||||
case input.upcase[0]
|
||||
when "P" # Quit
|
||||
$shutdown = 1
|
||||
puts 'Shutting down...'
|
||||
when "O" # Get status
|
||||
puts 'Not implemented yet. Press \'Enter\' key to continue.'
|
||||
gets
|
||||
when "Q" # Set step size
|
||||
print 'Enter new step size > '
|
||||
move_size_temp = gets
|
||||
$move_size = move_size_temp.to_i if move_size_temp.to_i > 0
|
||||
when "G" # Set step delay (seconds)
|
||||
print 'Enter new delay in seconds > '
|
||||
command_delay_temp = gets
|
||||
$command_delay = command_delay_temp.to_i if command_delay_temp.to_i > 0
|
||||
when "Y" # Water
|
||||
send_single_command('DOSE WATER', 0, 0, 0, 15, 0, $command_delay)
|
||||
when "Z" # Move to home
|
||||
send_single_command('HOME Z', 0, 0, 0, 0, 0, $command_delay)
|
||||
when "X" # Move to home
|
||||
send_single_command('HOME X', 0, 0, 0, 0, 0, $command_delay)
|
||||
when "C" # Move to home
|
||||
send_single_command('HOME Y',0 ,0 ,-$move_size, 0, 0, $command_delay)
|
||||
when "W" # Move forward
|
||||
send_single_command('MOVE RELATIVE',0,$move_size, 0, 0, 0, $command_delay)
|
||||
when "S" # Move back
|
||||
send_single_command('MOVE RELATIVE',0,-$move_size, 0, 0, 0, $command_delay)
|
||||
when "A" # Move left
|
||||
send_single_command('MOVE RELATIVE', -$move_size, 0, 0, 0, 0, $command_delay)
|
||||
when "D" # Move right
|
||||
send_single_command('MOVE RELATIVE', $move_size, 0, 0, 0, 0, $command_delay)
|
||||
when "R" # Move up
|
||||
send_single_command('MOVE RELATIVE', 0, 0, $move_size, 0, 0, $command_delay)
|
||||
when "F" # Move down
|
||||
send_single_command("MOVE RELATIVE", 0, 0, -$move_size, 0, 0, $command_delay)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
# Read about factories at https://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :user do
|
||||
name Faker::Name.name
|
||||
email Faker::Internet.email
|
||||
password Faker::Internet.password(8)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
module Helpers
|
||||
def sign_in_as(user)
|
||||
#TODO: Sign in via Warden instead.
|
||||
visit new_user_session_path
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_button 'Sign in'
|
||||
end
|
||||
end
|
|
@ -1,7 +1,32 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User Session' do
|
||||
xit 'logs the user in' do
|
||||
it 'logs the user in' do
|
||||
user = FactoryGirl.create(:user)
|
||||
visit new_user_session_path
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_button 'Sign in'
|
||||
expect(page).to have_content('Signed in successfully.')
|
||||
end
|
||||
|
||||
it 'edits user settings' do
|
||||
user = FactoryGirl.create(:user)
|
||||
sign_in_as(user)
|
||||
visit edit_user_registration_path
|
||||
old_email = user.email
|
||||
new_email = Faker::Internet.email
|
||||
fill_in 'user_email', with: new_email
|
||||
fill_in 'user_current_password', with: user.password
|
||||
click_button 'Update'
|
||||
expect(page).to have_content('Your account has been updated successfully.')
|
||||
expect(user.reload.email).to eq(new_email)
|
||||
end
|
||||
|
||||
it 'logs the user out' do
|
||||
user = FactoryGirl.create(:user)
|
||||
sign_in_as(user)
|
||||
click_link 'Sign out'
|
||||
expect(page).to have_content('Signed out successfully.')
|
||||
end
|
||||
end
|
|
@ -8,6 +8,7 @@ require File.expand_path("../../config/environment", __FILE__)
|
|||
require 'rspec/rails'
|
||||
require 'capybara/rails'
|
||||
require 'capybara/rspec'
|
||||
require 'features/helpers'
|
||||
# Requires supporting ruby files with custom matchers and macros, etc, in
|
||||
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
||||
# run as spec files by default. This means that files in spec/support that end
|
||||
|
@ -19,6 +20,8 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
|||
|
||||
RSpec.configure do |config|
|
||||
|
||||
config.include Helpers
|
||||
|
||||
config.after do
|
||||
Mongoid.purge!
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue