asic_rs/data/device/models/
mod.rs1#[cfg(feature = "python")]
2use pyo3::prelude::*;
3
4use super::{MinerFirmware, MinerMake};
5use antminer::AntMinerModel;
6use avalon::AvalonMinerModel;
7use bitaxe::BitaxeModel;
8use braiins::BraiinsModel;
9use epic::EPicModel;
10use serde::{Deserialize, Serialize};
11use std::{fmt::Display, str::FromStr};
12use whatsminer::WhatsMinerModel;
13
14pub mod antminer;
15pub mod avalon;
16pub mod bitaxe;
17pub mod braiins;
18pub mod epic;
19pub mod whatsminer;
20
21#[derive(Debug, Clone)]
22pub enum ModelSelectionError {
23 UnknownModel(String),
24 NoModelResponse,
25 UnexpectedModelResponse,
26}
27
28impl Display for ModelSelectionError {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 ModelSelectionError::UnknownModel(model) => write!(f, "Unknown model: {}", model),
32 ModelSelectionError::NoModelResponse => write!(f, "No response when querying model"),
33 ModelSelectionError::UnexpectedModelResponse => {
34 write!(f, "Response to model query was formatted unexpectedly")
35 }
36 }
37 }
38}
39
40impl std::error::Error for ModelSelectionError {}
41
42impl FromStr for WhatsMinerModel {
43 type Err = ModelSelectionError;
44
45 fn from_str(s: &str) -> Result<Self, Self::Err> {
46 serde_json::from_value(serde_json::Value::String(s.to_string()))
47 .map_err(|_| ModelSelectionError::UnknownModel(s.to_string()))
48 }
49}
50impl FromStr for AntMinerModel {
51 type Err = ModelSelectionError;
52
53 fn from_str(s: &str) -> Result<Self, Self::Err> {
54 serde_json::from_value(serde_json::Value::String(s.to_string()))
55 .map_err(|_| ModelSelectionError::UnknownModel(s.to_string()))
56 }
57}
58impl FromStr for BitaxeModel {
59 type Err = ModelSelectionError;
60
61 fn from_str(s: &str) -> Result<Self, Self::Err> {
62 serde_json::from_value(serde_json::Value::String(s.to_string()))
63 .map_err(|_| ModelSelectionError::UnknownModel(s.to_string()))
64 }
65}
66
67impl FromStr for BraiinsModel {
68 type Err = ModelSelectionError;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 serde_json::from_value(serde_json::Value::String(s.to_string()))
72 .map_err(|_| ModelSelectionError::UnknownModel(s.to_string()))
73 }
74}
75
76impl FromStr for AvalonMinerModel {
77 type Err = ModelSelectionError;
78
79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 serde_json::from_value(serde_json::Value::String(s.to_string()))
81 .map_err(|_| ModelSelectionError::UnknownModel(s.to_string()))
82 }
83}
84
85impl FromStr for EPicModel {
86 type Err = ModelSelectionError;
87
88 fn from_str(s: &str) -> Result<Self, Self::Err> {
89 serde_json::from_value(serde_json::Value::String(s.to_string()))
90 .map_err(|_| ModelSelectionError::UnknownModel(s.to_string()))
91 }
92}
93
94#[cfg_attr(feature = "python", pyclass(str, module = "asic_rs"))]
95#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Serialize, Deserialize)]
96#[serde(untagged)]
97pub enum MinerModel {
98 AntMiner(AntMinerModel),
99 WhatsMiner(WhatsMinerModel),
100 Braiins(BraiinsModel),
101 Bitaxe(BitaxeModel),
102 AvalonMiner(AvalonMinerModel),
103 EPic(EPicModel),
104}
105
106impl Display for MinerModel {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 match self {
109 MinerModel::AntMiner(m) => Ok(m.fmt(f)?),
110 MinerModel::WhatsMiner(m) => Ok(m.fmt(f)?),
111 MinerModel::Braiins(m) => Ok(m.fmt(f)?),
112 MinerModel::Bitaxe(m) => Ok(m.fmt(f)?),
113 MinerModel::EPic(m) => Ok(m.fmt(f)?),
114 MinerModel::AvalonMiner(m) => Ok(m.fmt(f)?),
115 }
116 }
117}
118
119impl From<MinerModel> for MinerMake {
120 fn from(model: MinerModel) -> Self {
121 match model {
122 MinerModel::AntMiner(_) => MinerMake::AntMiner,
123 MinerModel::WhatsMiner(_) => MinerMake::WhatsMiner,
124 MinerModel::Braiins(_) => MinerMake::Braiins,
125 MinerModel::Bitaxe(_) => MinerMake::Bitaxe,
126 MinerModel::EPic(_) => MinerMake::EPic,
127 MinerModel::AvalonMiner(_) => MinerMake::AvalonMiner,
128 }
129 }
130}
131
132pub(crate) struct MinerModelFactory {
133 make: Option<MinerMake>,
134 firmware: Option<MinerFirmware>,
135}
136
137impl MinerModelFactory {
138 pub fn new() -> Self {
139 MinerModelFactory {
140 make: None,
141 firmware: None,
142 }
143 }
144
145 pub(crate) fn with_make(&mut self, make: MinerMake) -> &Self {
146 self.make = Some(make);
147 self
148 }
149 pub(crate) fn with_firmware(&mut self, firmware: MinerFirmware) -> &Self {
150 self.firmware = Some(firmware);
151 self
152 }
153
154 pub(crate) fn parse_model(&self, model_str: &str) -> Result<MinerModel, ModelSelectionError> {
155 match self.make {
156 Some(MinerMake::AntMiner) => {
157 let model = AntMinerModel::from_str(model_str)?;
158 Ok(MinerModel::AntMiner(model))
159 }
160 Some(MinerMake::WhatsMiner) => {
161 let model = WhatsMinerModel::from_str(model_str)?;
162 Ok(MinerModel::WhatsMiner(model))
163 }
164 Some(MinerMake::Bitaxe) => {
165 let model = BitaxeModel::from_str(model_str)?;
166 Ok(MinerModel::Bitaxe(model))
167 }
168 Some(MinerMake::AvalonMiner) => {
169 let model = AvalonMinerModel::from_str(model_str)?;
170 Ok(MinerModel::AvalonMiner(model))
171 }
172 None => match self.firmware {
173 Some(MinerFirmware::BraiinsOS) => {
174 match (
175 AntMinerModel::from_str(model_str),
176 BraiinsModel::from_str(model_str),
177 ) {
178 (Ok(model), _) => Ok(MinerModel::AntMiner(model)),
179 (_, Ok(model)) => Ok(MinerModel::Braiins(model)),
180 (Err(am_err), _) => Err(am_err),
182 }
183 }
184 Some(MinerFirmware::EPic) => {
185 match (
186 AntMinerModel::from_str(model_str),
187 WhatsMinerModel::from_str(model_str),
188 EPicModel::from_str(model_str),
189 ) {
190 (Ok(model), _, _) => Ok(MinerModel::AntMiner(model)),
191 (_, Ok(model), _) => Ok(MinerModel::WhatsMiner(model)),
192 (_, _, Ok(model)) => Ok(MinerModel::EPic(model)),
193 (Err(am_err), _, _) => Err(am_err),
195 }
196 }
197 Some(MinerFirmware::LuxOS) => match AntMinerModel::from_str(model_str) {
198 Ok(model) => Ok(MinerModel::AntMiner(model)),
199 Err(am_err) => Err(am_err),
200 },
201 Some(MinerFirmware::Marathon) => match AntMinerModel::from_str(model_str) {
202 Ok(model) => Ok(MinerModel::AntMiner(model)),
203 Err(am_err) => Err(am_err),
204 },
205 Some(MinerFirmware::VNish) => match AntMinerModel::from_str(model_str) {
206 Ok(model) => Ok(MinerModel::AntMiner(model)),
207 Err(am_err) => Err(am_err),
208 },
209 Some(MinerFirmware::HiveOS) => match AntMinerModel::from_str(model_str) {
210 Ok(model) => Ok(MinerModel::AntMiner(model)),
211 Err(am_err) => Err(am_err),
212 },
213 Some(MinerFirmware::Stock) => unreachable!(),
215 None => unreachable!(),
217 },
218 Some(MinerMake::Braiins) => unreachable!(),
220 Some(MinerMake::EPic) => unreachable!(),
221 }
222 }
223}