Packages
A library for generating fake GPS data or load GPS from GPX file/string using for dev/test. The library generates GPSs for simulating a route and scalable for test workload.
Current section
Files
Jump to
Current section
Files
lib/worker.ex
defmodule LocationSimulator.Worker do
@moduledoc """
"""
require Logger
import LocationSimulator.Gps
def start_link(arg) do
pid = spawn_link(__MODULE__, :init, [arg])
{:ok, pid}
end
def init(config) when is_map(config) do
state = %{
start_time: get_timestamp(),
success: 0,
failed: 0,
error: 0
}
id = Map.get(config, :id, self())
%{callback: mod} = config
Logger.debug("#{inspect id}, call start event")
# send start event
config = case mod.start(config, state) do
{:ok, new_config} ->
new_config
{:error, reason} ->
err = "call start event failed: #{inspect reason}"
Logger.error(err)
raise err
end
:rand.seed(:exsss)
# random start point.
{lati, long} = generate_pos()
gps = %{
timestamp: 0,
long: long,
lati: lati
}
state = Map.put(state, :gps, gps)
counter = Map.get(config, :event, :infinity)
Logger.debug("start loop with counter: #{inspect counter}")
loop_event(config, state, counter)
end
def child_spec(opts) when is_map(opts) do
%{
id: Map.get(opts, :id, __MODULE__),
start: {__MODULE__, :start_link, [opts]},
type: :worker,
restart: Map.get(opts, :restart, :temporary),
shutdown: Map.get(opts, :shutdown, :brutal_kill)
}
end
defp loop_event(config, state, 0) do
stop_time = get_timestamp()
state = Map.put(state, :stop_time, stop_time)
%{callback: mod} = config
# send stop event
config = case mod.stop(config, state) do
{:ok, new_config} ->
new_config
{:error, reason} ->
err = "call start event failed: #{inspect reason}"
Logger.error(err)
raise err
end
%{start_time: start_time} = state
%{success: s} = state
%{failed: f} = state
%{error: e} = state
id = Map.get(config, :id, self())
Logger.debug "Worker(#{inspect id}) DONE!, time: #{stop_time - start_time}s, success: #{s}, failed: #{f}, error: #{e}"
end
defp loop_event(config, %{gps: last_gps} = state, counter) do
{lati, long} = generate_next_pos(last_gps.lati, last_gps.long, Enum.random(1..5), Enum.random(1..5))
%{interval: interval} = config
%{random_range: random_range} = config
sleep_time = interval + Enum.random(0..random_range)
Process.sleep(sleep_time)
new_gps = %{
timestamp: sleep_time + last_gps.timestamp,
long: long,
lati: lati,
alti: 0
}
state = Map.put(state, :gps, new_gps)
%{callback: mod} = config
{config, state, counter} =
case mod.event(config, state) do
{:ok, config} ->
{config, Map.update!(state, :success, &(&1 + 1)), counter}
{:error, reason} ->
Logger.debug "failed to post data return code: #{inspect reason}"
{config, Map.update!(state, :failed, &(&1 + 1)), counter}
{:stop, reason} ->
Logger.debug "stop worker, reason: #{inspect reason}"
{config, state, :stop}
end
case counter do
:infinity ->
loop_event(config, state, counter)
:stop ->
id = Map.get(config, :id, self())
Logger.debug("#{inspect id} stop by callback, reason: #{inspect id}")
_ ->
loop_event(config, state, counter-1)
end
end
defp get_timestamp do
:os.system_time(:seconds)
end
end