Skip to content

Instantly share code, notes, and snippets.

@tjws052009
Created December 5, 2022 03:31
Show Gist options
  • Save tjws052009/cd960e9e2d12d6c94e198dcd439253de to your computer and use it in GitHub Desktop.
Save tjws052009/cd960e9e2d12d6c94e198dcd439253de to your computer and use it in GitHub Desktop.
Create semi-realtime demo data which includes geo_point and some sensor-like data for Elasticsearch.
# example for running this script
# ES_URL="xxyyzz.es.asia-northeast1.gcp.cloud.es.io" KB_URL="xxyyzz.kb.asia-northeast1.gcp.cloud.es.io" ES_PORT="9243" ES_USER="elastic" ES_PASSWORD="xxyyzz" ruby gen.rb
#
# WARNING:
# This script deletes an index while processing, make sure you don't forget to comment that out if you plan to keep the index.
require 'base64'
require 'json'
require 'net/http'
ES_URL = ENV['ES_URL']
KB_URL = ENV['KB_URL']
ES_PORT = ENV['ES_PORT']
ES_USER = ENV['ES_USER']
ES_PASSWORD = ENV['ES_PASSWORD']
index_name = ['map-demopoint-1']
http = Net::HTTP.new(ES_URL, ES_PORT)
http_kb = Net::HTTP.new(KB_URL, ES_PORT)
basic_auth_token = Base64.encode64("#{ES_USER}:#{ES_PASSWORD}")
http.use_ssl = true
http_kb.use_ssl = true
header = {
"Content-Type": "application/json",
"Authorization": "Basic #{basic_auth_token}"
}
header_kb = {
"Content-Type": "application/json",
"Authorization": "Basic #{basic_auth_token}",
"kbn-xsrf": "true"
}
class Target
attr_accessor :name, :location, :battery, :status, :tags, :disp_mag, :disp_ang
NAME_LIST = %w(
Andy
Blake
Chris
Don
Eric
Felix
George
Harry
John
Kat
Lester
Mike
Natalie
Oz
Pat
Ray
James
Robert
Michael
David
William
Richard
Mary
)
STATUS_LIST = %w(
green
green
green
green
green
green
green
green
green
yellow
red
)
TAGS_LIST = %w(
car
taxi
bus
bicycle
truck
)
MIN_Y = 35.668365
MAX_Y = 35.697101
MIN_X = 139.729863
MAX_X = 139.775394
CENTER = [(MIN_X + MAX_X) / 2, (MIN_Y + MAX_Y) / 2]
GPS_PERCISION = 1e-4
@@num_targets = 0
def update_disp(prob = 0.1)
rand < prob
end
def update_location
return if self.battery == 0
current_loc1 = self.location[0]
current_loc2 = self.location[1]
if update_disp
@disp_mag = rand(-5..5) * GPS_PERCISION
@disp_ang = rand(360)
end
disp_x = @disp_mag * Math.cos(@disp_ang * Math::PI / 180)
disp_y = @disp_mag * Math.sin(@disp_ang * Math::PI / 180)
self.location[0] = current_loc1 + disp_x
self.location[1] = current_loc2 + disp_y
x_check = self.location[0] < MIN_X || self.location[0] > MAX_X
y_check = self.location[1] < MIN_Y || self.location[1] > MAX_Y
if x_check || y_check
@disp_ang = @disp_ang - 180
disp_x = @disp_mag * Math.cos(@disp_ang * Math::PI / 180)
disp_y = @disp_mag * Math.sin(@disp_ang * Math::PI / 180)
self.location[0] = current_loc1 + disp_x
self.location[1] = current_loc2 + disp_y
end
end
def update_battery
@batt_cycle = 0 if @batt_cycle.nil?
current_battery = self.battery
if self.battery > 0
self.battery = current_battery - (rand(0..1))
else
@batt_cycle = @batt_cycle + 1
if @batt_cycle > 50
@batt_cycle = 0
self.battery = 100
end
end
end
def update_status
if self.battery > 30
self.status = "green"
elsif self.battery > 0
self.status = "yellow"
else
self.status = "red"
end
end
def next_step
update_location
update_battery
update_status
end
def to_hash
res = {}
res[:name] = @name
res[:location] = @location
res[:battery] = @battery
res[:status] = @status
res[:tags] = @tags
res
end
def self.gen_name
NAME_LIST[@@num_targets]
end
def self.gen_loc
[rand(MIN_X..MAX_X), rand(MIN_Y..MAX_Y)]
end
def self.gen_battery
(rand * 100).to_i
end
def self.gen_status
# STATUS_LIST.sample
"green"
end
def self.gen_tags
TAGS_LIST.sample
end
def initialize(input = {})
@name = input[:name] || self.class.gen_name
@location = input[:location ] || self.class.gen_loc
@battery = input[:battery] || self.class.gen_battery
@status = input[:status] || self.class.gen_status
@tags = input[:tags] || self.class.gen_tags
@disp_mag = 0
@disp_ang = 0
@@num_targets += 1
end
end
# delete existing index
index_name.each do |ind_name|
r0 = http.delete("/#{ind_name}", header)
end
# generate index with mapping
# location x y as geo-point field
data = '{"mappings":{"properties":{"@timestamp":{"type":"date"},"name":{"type":"text","fields":{"keyword":{"type":"keyword"}}},"location":{"type":"geo_point"},"battery":{"type":"double"},"status":{"type":"text","fields":{"keyword":{"type":"keyword"}}},"tags":{"type":"text","fields":{"keyword":{"type":"keyword"}}}}}}'
index_name.each do |ind_name|
r1 = http.put("/#{ind_name}", data, header)
end
kb_data = '{ "data_view": { "title": "map-demopoint-*", "timeFieldName": "@timestamp" } }'
r1 = http_kb.post("/api/data_views/data_view", kb_data, header_kb)
# puts r1.message
targets = []
10.times do |ind|
target = Target.new
targets << target
end
last_tick = Time.now
while true
sleep 2
current_tick = Time.now
if current_tick - last_tick >= 1
last_tick = last_tick + 1
output = []
targets.each_with_index do |t, ind|
t.next_step
res = t.to_hash
res[:"@timestamp"] = current_tick.strftime("%Y-%m-%dT%H:%M:%S%z")
output << res
end
out_str = ""
output.each_with_index do |out, ind|
out_str << '{"index":{"_index":"' + index_name[ind % index_name.length] + '"}}'
out_str << "\n"
out_str << out.to_json
out_str << "\n"
end
out_str << "\n"
puts Time.now
puts out_str
r2 = http.post("/_bulk", out_str, header)
puts r2.message
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment